Problems with Picker

979 views
Skip to first unread message

Zhetong Fang

unread,
Dec 4, 2012, 9:44:02 AM12/4/12
to calaba...@googlegroups.com
When I tried to simulate the actions to scroll the Picker, I got some problems.

I don't know much about ruby but I found some information on https://groups.google.com/forum/?fromgroups=#!topic/calabash-ios/s1Z6se1uMY4
Firstly, the 700 lines code doesn't seems to be helpful as I'm using the Date Picker with Date Mode but I still find something on picker_steps.rb in https://gist.github.com/4103369
And I tried to use it directly.

Then the problem comes, every time I want to scroll the picker, it will quickly goes back, no matter how many rows to be scrolled.

def picker_current_index_for_column (column)
  arr = query("pickerTableView", :selectionBarRow)
  arr[column]
end

def picker_current_index_for_column_is(column, val)
  picker_current_index_for_column(column) == val
end

def previous_index_for_column (column)
  picker_current_index_for_column(column) - 1
end

def picker_next_index_for_column (column)
  picker_current_index_for_column(column) + 1
end

def picker_scroll_down_on_column(column)
  new_row = previous_index_for_column column
  scroll_to_row("pickerTableView index:#{column}", new_row)
end

def picker_scroll_up_on_column(column)
  new_row = picker_next_index_for_column column
  scroll_to_row("pickerTableView index:#{column}", new_row)
end

This is the definition in picker_steps.rb and When I tried to use

picker_scroll_up_on_column 0, the problem comes.


I have another Picker used in another program, the problem is quite similar.

This time the Picker will not goes back, but it stopped after the first step, even though I call it several times.

I think it's because the data haven't been updated the only change is the dispaly.


So I tried to use swipe to do a similar thing.


def picker_swipe_up_on_column(column)

    swipe("up", {:query => "pickerTableView index:#{column}"})

end


This time the picker_swipe_up_on_column 0 works quid well and the changing has been saved.

But I don't know if it is possible to do something like swipe_to_row,etc.


By the way

When using scroll_to_row to select a row, the method


pickerView:didSelectRow:inComponent:


is not called. It seems that the relevant event is not being fired when using scroll_to_row.


Any idea anyone?


Joshua Moody

unread,
Dec 4, 2012, 10:28:00 AM12/4/12
to calaba...@googlegroups.com
i am the maintainer of the gist:  https://gist.github.com/4103369

i recently discovered that it does not work for iOS 6.  i have fix, but have not tested enough to submit it. are you using iOS 6?

Then the problem comes, every time I want to scroll the picker, it will quickly goes back, no matter how many rows to be scrolled.

this can happen if you have a maximum or minimum  date on the picker.  do you have a max or min date?

When using scroll_to_row to select a row, the method
pickerView:didSelectRow:inComponent:

i have not seen this happen.

Trevor mentioned that he uses:

 def select_date(date_string) 
   date = Date.parse(date_string) 

   # Go in order of year, month, day so that the expected day range is available 
   query("view:'_UIDatePickerView'", [{:selectRow => date.year - 1},  {:inComponent => 2}, {:animated => 0}]) 
   query("view:'_UIDatePickerView'", [{:selectRow => date.month - 1}, {:inComponent => 0}, {:animated => 0}]) 
   query("view:'_UIDatePickerView'", [{:selectRow => date.day - 1},   {:inComponent => 1}, {:animated => 0}]) 
 end 

you could give that a try.



Zhetong Fang

unread,
Dec 4, 2012, 10:33:40 AM12/4/12
to calaba...@googlegroups.com
I have tried that yet, still the same problem,

it seems the only change is the display, and that never been saved, as the data should be updatedautomatically and it does when I manually do that.

在 2012年12月4日星期二UTC下午3时28分00秒,Joshua Moody写道:

Zhetong Fang

unread,
Dec 4, 2012, 10:47:15 AM12/4/12
to calaba...@googlegroups.com

Here is my definition


def select_date(date_string)

    date = Date.parse(date_string)

    query("view:'_UIDatePickerView'", [{:selectRow => date.month - 1}, {:inComponent => 0}, {:animated => 0}])

    query("view:'_UIDatePickerView'", [{:selectRow => date.day - 1},   {:inComponent => 1}, {:animated => 0}])

    query("view:'_UIDatePickerView'", [{:selectRow => date.year - 1},  {:inComponent => 2}, {:animated => 0}])

end


Then /^I select the date to "([^\"]*)"$/ do |date_string|

    select_date date_string

    sleep(STEP_PAUSE)

end


And when I use


  Then I select the date to "July 12 1988"


The display is




And when I manually do that, the display will be




You can see the data above hasn't been updated.



在 2012年12月4日星期二UTC下午3时28分00秒,Joshua Moody写道:

Joshua Moody

unread,
Dec 4, 2012, 11:06:27 AM12/4/12
to calaba...@googlegroups.com
this:


 query("view:'_UIDatePickerView'", [{:selectRow => date.month - 1}, {:inComponent => 0}, {:animated => 0}])

does not cause a touch event, which means that whatever action/delegate methods you are using to update your ui are not going to be called.

you will need use swipe to trigger a touch a event.

i grabbed this from the gist:

  # REQUIRED
  sleep(PICKER_STEP_PAUSE)

  # the query does not create a UIControlEventValueChanged event, so we have to
  # to a touch event

  # if the picker is in time mode, then we dont need to worry about min/max
  # if the picker is date or date time mode, i think the first column is
  # always scrollable up _and_ it sends an event even if the date is beyond
  # the maximum date
  picker_scroll_up_on_column 0
  sleep(PICKER_STEP_PAUSE)
  picker_scroll_down_on_column 0
  sleep(PICKER_STEP_PAUSE)

can you please tell me what iOS(es) you are using?



Zhetong Fang

unread,
Dec 4, 2012, 11:13:38 AM12/4/12
to calaba...@googlegroups.com
I use iOS 5.1 and iOS 6.0

在 2012年12月4日星期二UTC下午4时06分27秒,Joshua Moody写道:

Joshua Moody

unread,
Dec 4, 2012, 11:21:16 AM12/4/12
to calaba...@googlegroups.com
can you please tell me what iOS(es) you are using?
 
I use iOS 5.1 and iOS 6.0

ok, the code in my gist will not work on iOS 6.0 because the class name of the date picker view changed. 

the gist  describes 2 ways to manipulate the date picker:

1. AUTOMATIC <== setting the date directly using a UIDatePicker category method
2. MANUAL <== setting the date by manipulating the picker wheels

which are you using?

Zhetong Fang

unread,
Dec 4, 2012, 11:27:32 AM12/4/12
to calaba...@googlegroups.com
I've tried to use MANUAL ways,

But it seems doesn't support the Date Mode so I don't know how to use it.

在 2012年12月4日星期二UTC下午4时21分16秒,Joshua Moody写道:

Joshua Moody

unread,
Dec 4, 2012, 11:48:10 AM12/4/12
to calaba...@googlegroups.com
you are correct.  it does not support the date mode. 

to solve your immediate problem, i suggest trying this:

def select_date(date_string)
  date = Date.parse(date_string)
  query("view:'_UIDatePickerView'", [{:selectRow => date.month - 1}, {:inComponent => 0}, {:animated => 0}])
  query("view:'_UIDatePickerView'", [{:selectRow => date.day - 1},   {:inComponent => 1}, {:animated => 0}])
  query("view:'_UIDatePickerView'", [{:selectRow => date.year - 1},  {:inComponent => 2}, {:animated => 0}])
  sleep(0.4)
  # the query does not create a UIControlEventValueChanged event, so we have to do a touch event
  picker_scroll_up_on_column 0
  sleep(0.4)
  picker_scroll_down_on_column 0
  sleep(0.4)
end



Zhetong Fang

unread,
Dec 4, 2012, 11:53:19 AM12/4/12
to calaba...@googlegroups.com
It works for the first column but the other two columns quickly goes back to default date

在 2012年12月4日星期二UTC下午4时48分10秒,Joshua Moody写道:

Zhetong Fang

unread,
Dec 4, 2012, 11:58:15 AM12/4/12
to calaba...@googlegroups.com
I've add the "touch" event to every step, and it work quite well now

def select_date(date_string)

    date = Date.parse(date_string)

    query("view:'_UIDatePickerView'", [{:selectRow => date.month - 1}, {:inComponent => 0}, {:animated => 0}])

    sleep(0.4)

    # the query does not create a UIControlEventValueChanged event, so we have to do a touch event

    picker_scroll_up_on_column 0

    sleep(0.4)

    picker_scroll_down_on_column 0

    sleep(0.4)

    query("view:'_UIDatePickerView'", [{:selectRow => date.day - 1},   {:inComponent => 1}, {:animated => 0}])

    sleep(0.4)

    # the query does not create a UIControlEventValueChanged event, so we have to do a touch event

    picker_scroll_up_on_column 1

    sleep(0.4)

    picker_scroll_down_on_column 1

    sleep(0.4)

    query("view:'_UIDatePickerView'", [{:selectRow => date.year - 1},  {:inComponent => 2}, {:animated => 0}])

    sleep(0.4)

    # the query does not create a UIControlEventValueChanged event, so we have to do a touch event

    picker_scroll_up_on_column 2

    sleep(0.4)

    picker_scroll_down_on_column 2

    sleep(0.4)

end



在 2012年12月4日星期二UTC下午4时48分10秒,Joshua Moody写道:

Trevor Harmon

unread,
Dec 4, 2012, 11:58:24 AM12/4/12
to calaba...@googlegroups.com
If the previous date was a non leap year, this code won't be able to select Feb 29 because there was no Feb 29 that year. Better to select year, then month, then day.

Also, it is not necessary to trigger delegate methods using a swipe and sleep. You can invoke them directly:

    query("pickerView", [{:selectRow => monthRow}, {:inComponent => 0}, {:animated => 0}])
    query("pickerView", :delegate, [{:pickerView => :__self__}, {:didSelectRow => monthRow}, {:inComponent => 0}])
    ...

Trevor

Zhetong Fang

unread,
Dec 4, 2012, 12:18:17 PM12/4/12
to calaba...@googlegroups.com
Could you give me some help for other Picker not only Date picker, for example only one column to select the weight.

Another similar problem is for TableView that I have no idea about how to scroll to a row.

touch ("view:'UITableViewCell' label marked:'#{cell_name}'")


seems only work when the cell is in the screen, so I have to scroll down to find it.


在 2012年12月4日星期二UTC下午4时58分24秒,Trevor Harmon写道:

Mashhood Rastgar

unread,
Dec 7, 2012, 2:02:38 AM12/7/12
to calaba...@googlegroups.com
Thanks for this Joshua,

However when I used this script I had to comment out the last 4 lines for it to work properly:


def select_date(date_string)
  date = Date.parse(date_string)
  query("view:'_UIDatePickerView'", [{:selectRow => date.month - 1}, {:inComponent => 0}, {:animated => 1}])
  query("view:'_UIDatePickerView'", [{:selectRow => date.day - 1},   {:inComponent => 1}, {:animated => 1}])
  query("view:'_UIDatePickerView'", [{:selectRow => date.year - 1},  {:inComponent => 2}, {:animated => 1}])
  sleep(0.4)
  # the query does not create a UIControlEventValueChanged event, so we have to do a touch event
  #picker_scroll_up_on_column 0
  #sleep(0.4)
  #picker_scroll_down_on_column 0
  #sleep(0.4)
end

Otherwise the initial selection was fine, but then it changed (after 0.4s) to an incorrect date. Not sure what the problem is, but its working now.

Trevor Harmon

unread,
Dec 7, 2012, 10:01:12 AM12/7/12
to calaba...@googlegroups.com
On Dec 6, 2012, at 11:02 PM, Mashhood Rastgar <mash...@gmail.com> wrote:

> However when I used this script I had to comment out the last 4 lines for it to work properly:
>
> def select_date(date_string)
> date = Date.parse(date_string)
> query("view:'_UIDatePickerView'", [{:selectRow => date.month - 1}, {:inComponent => 0}, {:animated => 1}])
> query("view:'_UIDatePickerView'", [{:selectRow => date.day - 1}, {:inComponent => 1}, {:animated => 1}])
> query("view:'_UIDatePickerView'", [{:selectRow => date.year - 1}, {:inComponent => 2}, {:animated => 1}])
> sleep(0.4)
> # the query does not create a UIControlEventValueChanged event, so we have to do a touch event
> #picker_scroll_up_on_column 0
> #sleep(0.4)
> #picker_scroll_down_on_column 0
> #sleep(0.4)
> end
>
> Otherwise the initial selection was fine, but then it changed (after 0.4s) to an incorrect date. Not sure what the problem is, but its working now.

I think the problem is that the scrolling code above is error-prone. Its intent is to trigger a value changed event while keeping the final date value as "date". That is, picker_scroll_up_on_column changes the value, but picker_scroll_down_on_column restores it. However, if you happen to choose a date where one column is already at the top, picker_scroll_up_on_column is a no-op, which means picker_scroll_down_on_column won't undo the scroll_up -- instead it will change the column to a new value.

Trevor

Joshua Moody

unread,
Dec 7, 2012, 10:47:25 AM12/7/12
to calaba...@googlegroups.com
trevor is correct - the code above will fail under a number of scenarios.


Zhetong Fang

unread,
Dec 7, 2012, 11:36:41 AM12/7/12
to calaba...@googlegroups.com
One suggestion for this:

def select_date(date_string)

    date = Date.parse(date_string)

    query("view:'_UIDatePickerView'", [{:selectRow => date.year - 1}, {:inComponent => 2}, {:animated => 1}])

    query("pickerView", :delegate, [{:pickerView => :__self__}, {:didSelectRow => date.year - 1}, {:inComponent => 2}])

    sleep(STEP_PAUSE)

    query("view:'_UIDatePickerView'", [{:selectRow => date.month - 1}, {:inComponent => 0}, {:animated => 1}])

    query("pickerView", :delegate, [{:pickerView => :__self__}, {:didSelectRow => date.month - 1}, {:inComponent => 0}])

    sleep(STEP_PAUSE)

    query("view:'_UIDatePickerView'", [{:selectRow => date.day - 1}, {:inComponent => 1}, {:animated => 1}])

    query("pickerView", :delegate, [{:pickerView => :__self__}, {:didSelectRow => date.day - 1}, {:inComponent => 1}])

    sleep(STEP_PAUSE)

end

Adding a STEP_PAUSE will make it a lot better to simulate a real person 

Mashhood Rastgar

unread,
Dec 7, 2012, 11:05:47 PM12/7/12
to calaba...@googlegroups.com
Awesome! Thanks guys.

Mashhood Rastgar

unread,
Dec 15, 2012, 1:03:02 AM12/15/12
to calaba...@googlegroups.com
Hello Zhetong,

I was trying to use this for the DateTime picker as well (the one with Thu Dec 13 on the left), could you please give an example of how to use this code for that component? I noticed that its a bit more trickier since that column has two labels "Thu" and "Dec 13", Im guessing that is not allowing me to select it.

Thanks! 

On Friday, 7 December 2012 21:36:41 UTC+5, Zhetong Fang wrote:

Zhetong Fang

unread,
Dec 18, 2012, 12:38:00 PM12/18/12
to calaba...@googlegroups.com
I'm afarid this solution is only for Date Mode.

For Date and Time mode, there is already some useful steps here




在 2012年12月15日星期六UTC上午6时03分02秒,Mashhood Rastgar写道:

Mashhood Rastgar

unread,
Dec 18, 2012, 10:34:40 PM12/18/12
to calaba...@googlegroups.com
Thanks. I ended writing a small script using recorded gestures, its a bit buggy but its getting there.

Alexander Khozya

unread,
Jan 22, 2013, 1:57:00 PM1/22/13
to calaba...@googlegroups.com
Hi Zhetong. Did you manage to get this script working on iOS6? It works for iOS 5 and below, but scrolling doesn't occur on iOS6.

Alexander Khozya

unread,
Jan 22, 2013, 1:57:42 PM1/22/13
to calaba...@googlegroups.com
Did you manage this code to work on iOS6? It works OK for iOS5 and below, but not for iOS6

Joshua Moody

unread,
Jan 22, 2013, 4:39:27 PM1/22/13
to calaba...@googlegroups.com
i updated the picker_steps.rb in this gist: https://gist.github.com/4103369  to work with iOS 5 and 6.

the trick was to take advantage of a private class and method:

query("pickerTableView index:'#{column}'", [{selectRow:new_row}, {animated:1}, {notify:1}])

i have been slowly migrating the date_picker_steps.rb portion of the gist to be more robust (but haven't added the changes to the gist yet).

Alexander Khozya

unread,
Jan 23, 2013, 4:27:15 AM1/23/13
to calaba...@googlegroups.com
Is there a way to modify this code to work in iOS6? 
   
query("view:'UIDatePickerView'", [{:selectRow => date.year}, {:inComponent => 2}, {:animated => 1}])
query("pickerView", :delegate, [{:pickerView => :__self__}, {:didSelectRow => date.year}, {:inComponent => 2}])
sleep(STEP_PAUSE)  
query("view:'UIDatePickerView'", [{:selectRow => date.month - 1}, {:inComponent => 0}, {:animated => 1}])
query("pickerView", :delegate, [{:pickerView => :__self__}, {:didSelectRow => date.month - 1}, {:inComponent => 0}])
sleep(STEP_PAUSE)
query("view:'UIDatePickerView'", [{:selectRow => date.day - 1}, {:inComponent => 1}, {:animated => 1}])
query("pickerView", :delegate, [{:pickerView => :__self__}, {:didSelectRow => date.day - 1}, {:inComponent => 1}])
sleep(STEP_PAUSE)

When I try to add your steps I receive errors:
/Users/AKhozya/Work/Git-repos/Badoo/Automation/Calabash/features/step_definitions/date_picker_steps.rb:198: warning: don't put space before argument parentheses /Users/AKhozya/Work/Git-repos/Badoo/Automation/Calabash/features/step_definitions/date_picker_steps.rb:704: warning: don't put space before argument parentheses /Users/AKhozya/Work/Git-repos/Badoo/Automation/Calabash/features/step_definitions/date_picker_steps.rb:169: syntax error, unexpected tSYMBEG, expecting kDO or '{' or '(' res = query("datePicker", [{hasCalabashAdditions:success_value}]) ^ /Users/AKhozya/Work/Git-repos/Badoo/Automation/Calabash/features/step_definitions/date_picker_steps.rb:210: syntax error, unexpected tSYMBEG, expecting kDO or '{' or '(' query("datePicker", [{respondsToSelector:"minuteInterval"}]) ^ /Users/AKhozya/Work/Git-repos/Badoo/Automation/Calabash/features/step_definitions/date_picker_steps.rb:210: syntax error, unexpected '}', expecting kEND query("datePicker", [{respondsToSelector:"minuteInterval"}]) ^ /Users/AKhozya/Work/Git-repos/Badoo/Automation/Calabash/features/step_definitions/date_picker_steps.rb:213: syntax error, unexpected tSYMBEG, expecting kDO or '{' or '(' res = query("datePicker", [{setDateWithString:date_time_str}, ^ /Users/AKhozya/Work/Git-repos/Badoo/Automation/Calabash/features/step_definitions/date_picker_steps.rb:214: syntax error, unexpected '}', expecting kEND ...KER_DATE__DATE_AND_TIME_FMT}"}, ^ /Users/AKhozya/Work/Git-repos/Badoo/Automation/Calabash/features/step_definitions/date_picker_steps.rb:215: odd number list for Hash {animated:animated.to_i}]) ^ /Users/AKhozya/Work/Git-repos/Badoo/Automation/Calabash/features/step_definitions/date_picker_steps.rb:215: syntax error, unexpected '}', expecting kEND {animated:animated.to_i}]) ^ (SyntaxError) /Library/Ruby/Gems/1.8/gems/cucumber-1.2.1/bin/../lib/cucumber/rb_support/rb_language.rb:129:in `load' /Library/Ruby/Gems/1.8/gems/cucumber-1.2.1/bin/../lib/cucumber/rb_support/rb_language.rb:129:in `load_code_file' /Library/Ruby/Gems/1.8/gems/cucumber-1.2.1/bin/../lib/cucumber/runtime/support_code.rb:171:in `load_file' /Library/Ruby/Gems/1.8/gems/cucumber-1.2.1/bin/../lib/cucumber/runtime/support_code.rb:83:in `load_files!' /Library/Ruby/Gems/1.8/gems/cucumber-1.2.1/bin/../lib/cucumber/runtime/support_code.rb:82:in `each' /Library/Ruby/Gems/1.8/gems/cucumber-1.2.1/bin/../lib/cucumber/runtime/support_code.rb:82:in `load_files!' /Library/Ruby/Gems/1.8/gems/cucumber-1.2.1/bin/../lib/cucumber/runtime.rb:175:in `load_step_definitions' /Library/Ruby/Gems/1.8/gems/cucumber-1.2.1/bin/../lib/cucumber/runtime.rb:40:in `run!' /Library/Ruby/Gems/1.8/gems/cucumber-1.2.1/bin/../lib/cucumber/cli/main.rb:43:in `execute!' /Library/Ruby/Gems/1.8/gems/cucumber-1.2.1/bin/../lib/cucumber/cli/main.rb:20:in `execute' /Library/Ruby/Gems/1.8/gems/cucumber-1.2.1/bin/cucumber:14 /usr/bin/cucumber:19:in `load' /usr/bin/cucumber:19

Krukow

unread,
Jan 24, 2013, 5:05:36 PM1/24/13
to calaba...@googlegroups.com
From the stack trace I see at least one bug: you're running ruby 1.8.7 and using ruby 1.9.x syntax:

 [{respondsToSelector:"minuteInterval"}]

please update to Ruby 1.9.3

Alternatively please replace all hash literals of form: x:y with :x => y

Alexander Khozya

unread,
Jan 30, 2013, 7:08:01 AM1/30/13
to calaba...@googlegroups.com
Thank you it helped.

Alexander Khozya

unread,
Jan 30, 2013, 7:12:57 AM1/30/13
to calaba...@googlegroups.com
Hi Joshua.
Is there an embedded step in your code to select birth date (or how to construct it basing on your gist?). Eg 21-02-1988 or 21-Feb-1988. Step "I change the date on the picker to" works only for date as I see. I can't select day-month-year in this step.

Thanks for your efforts!

On Wednesday, January 23, 2013 1:39:27 AM UTC+4, Joshua Moody wrote:

Joshua Moody

unread,
Jan 30, 2013, 7:19:09 AM1/30/13
to calaba...@googlegroups.com
no, nothing yet.  i am working on a better version of the date picking code, but dont hold your breath.

good luck.


Alexander Khozya

unread,
Jan 31, 2013, 4:25:05 AM1/31/13
to calaba...@googlegroups.com
Umm, do you have any idea/hint how to make this code work on iOS6. Maybe there is a way (like determine that is ran in iOS6 and change few lines). AFAIK DatePicker class is named differently in iOS6 and this is the root cause of issue.
Thanks in advance!


query("view:'UIDatePickerView'", [{:selectRow => date.year}, {:inComponent => 2}, {:animated => 1}])
query("pickerView", :delegate, [{:pickerView => :__self__}, {:didSelectRow => date.year}, {:inComponent => 2}])
sleep(STEP_PAUSE)
query("view:'UIDatePickerView'", [{:selectRow => date.month - 1}, {:inComponent => 0}, {:animated => 1}])
query("pickerView", :delegate, [{:pickerView => :__self__}, {:didSelectRow => date.month - 1}, {:inComponent => 0}])
sleep(STEP_PAUSE)
query("view:'UIDatePickerView'", [{:selectRow => date.day - 1}, {:inComponent => 1}, {:animated => 1}])
query("pickerView", :delegate, [{:pickerView => :__self__}, {:didSelectRow => date.day - 1}, {:inComponent => 1}])
sleep(STEP_PAUSE)

Mashhood Rastgar

unread,
Jan 31, 2013, 4:28:03 AM1/31/13
to calaba...@googlegroups.com
Hello Alex,

I am using the function below on iOS6:
def performSelection(rowNumber, colNumber) 
  query("view:'_UIDatePickerView'", [{:selectRow => rowNumber}, {:inComponent => colNumber}, {:animated => 0}])
  query("pickerView", :delegate, [{:pickerView => :__self__}, {:didSelectRow => rowNumber}, {:inComponent => colNumber}])
  sleep(SLEEP_TIME)
end

Hope this helps..
--
You received this message because you are subscribed to the Google Groups "calabash-ios" group.
To unsubscribe from this group and stop receiving emails from it, send an email to calabash-ios...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Reply all
Reply to author
Forward
0 new messages