问题
I have a UIActionSheet containing a picker and a UIToolbar. On the UIToolBar there is a save button. However, some of my users reported pressing the save button before the UIPickerView stops spinning thus only retrieving the initial value (before spinning).
Is there a way to get the currently selected item of the UIPickerView once the user taps save or get feedback of the active selected item while it's spinning?
Thanks
回答1:
Even if they dismiss the picker while it's still spinning, the picker will still call the delegate with the final selected row once it stops, even if it isn't visible. Assuming you haven't deallocated it yet, you can set the delegate receiver to check if the picker is visible, and if it isn't, save the selected value.
I do this assuming it's clear the user isn't scrolling to a random value - usually when they scroll and dismiss without waiting for it to settle, it means they scrolled to either the very top or very bottom of the list. I'd say you can safely use the result of the delegate in these two cases.
回答2:
Have you ever thought about using the titleForRow
method to figure this out. As the pickerview
is scrolling, your titleForRow
method is being called to populate the rows above or below the currently viewed row(depending on which way the picker is spinning). When the picker stops, the didSelectRow
method is called and the row returned is 2 rows from the last row populated in the titleForRow
method.
I would think that you could choose to stop the picker at some point (timers to detect point that are used to tell code in titleForRow
to capture component and row from the call) in the scrolling and then do a selectRow
to set the value to what you want it to be after it stops spinning (and didSelectRow
is called).
回答3:
I don't think this is a problem you're going to be able to solve with UIPickerView
by itself.
There is no way to now which row is selected without the animation stopping (and thus the picker view selecting the row it stopped on). The only way would be to tell the picker which row to stop on, by using the selectRow:inComponent:animated:
but how will you know which row that is? You don't know because the picker is spinning...
I think this is just a limitation of the UIPickerView
and Apple would likely describe it as expected behaviour.
回答4:
I had the same problem... I fixed it by simply adding the following code line on the method that closes or selects the picker value.
[_picker selectRow:[_picker selectedRowInComponent:0] inComponent:0 animated:YES];
回答5:
Just found solution, which works for my case. I don't need that last update event, generated when picker stops spinning after user dismissed it. So this method stops scrolling and don't causes new update selection event. Seems you'll going to check if selections are ok in picker after this (I don't care, I reselect values when I show picker).
- (void)_resetPickerViewDelegates {
id delegate = [_pickerView.delegate retain];
id dataSource = [_pickerView.dataSource retain];
_pickerView.delegate = nil;
_pickerView.dataSource = nil;
[_pickerView reloadAllComponents];
_pickerView.delegate = delegate;
_pickerView.dataSource = dataSource;
[delegate release];
[dataSource release];
}
回答6:
On "save" button click, You can retrieve the selected object from your component by
[component1Array objectAtIndex:[myPicker selectedRowInComponent:1]];
where,
- "component1Array" is an NSArray or NSMutableArray, object which used to display the objects (raw contents) in your component.
- "myPicker" is an UIPickerView object which displays the picker.
- "[myPicker selectedRowInComponent:1]" will return the currently selected raw no from the myPicker in component '1'.
And "[myPicker selectedRowInComponent:2]" will return the currently selected raw no from the myPicker in component '2'. You can retrieve the selected object from your component2 by
[component2Array objectAtIndex:[myPicker selectedRowInComponent:2]];
Hope it works for you.
回答7:
This might be a "hack," but it works. My case is slightly different. I'm using one UIPicker
, but can change what object it is manipulation.
My issue was that you could select one object, spin the picker, and while it is finishing its spin, select a different object. What ended up happening was the new object was getting the final value of that spin, rather than it being ignored.
What I did what when setting up the UIPicker
I'd give it a unique tag
based on the object that it was supposed to update.
- (void)updatePickerView:(UIPickerView*)pickerView
{
...
pickerView.tag = [self.myObject.position integerValue];
[pickerView selectRow:i inComponent:0 animated:NO];
}
Then when it finishes its spin, I check to make sure that tag lines up still.
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
if (pickerView.tag == [self.myObject.position integerValue]) {
...
}
}
I'm not sure how it is functioning on Apple's side, but this was enough to make it work for me.
As a side note, and I'm not sure if this matters, but my UIPicker
is in a UITableViewCell
but since it is a reusable cell and because I was having the issues that I was, I assume the UIPicker is the same when it is moved from one position to another (as there is only one on screen at a time).
回答8:
var isSpinning = false (Global)
func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView {
self.isSpinning = true
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
self.isSpinning = false
}
来源:https://stackoverflow.com/questions/4840824/programmatically-stop-uipickerview-animation-on-iphone