I need to launch pickerView programatically from code after receiving some array from server response
I use following code
_locationsPickerData = [NSArray arrayWithArray:offeredLocations];
UIPickerView *pickerView = [[UIPickerView alloc] init];
UIToolbar *toolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.view.frame), 44)];
UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(locationsPickerDoneAction:)];
UIBarButtonItem *flexibleSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
[toolbar setItems:@[flexibleSpace, doneButton]];
toolbar.translucent = YES;
pickerView.delegate = self;
pickerView.dataSource = self;
pickerView.accessibilityIdentifier = @"locationsPicker";
[_locationTextField setInputView:pickerView];
[_locationTextField setInputAccessoryView:toolbar];
I tried to launch picker view by [_locationTextField becomeFirstResponder];
- but application crashes in such case.
And yes, I subscribed for UIPickerViewDataSource, UIPickerViewDelegate
.
And I implemented methods from protocols
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
// the number of columns of data
return 1;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
// the number of rows of data
return _locationsPickerData.count;
}
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
// the data to return for the row and component (column) that's being passed in
return _locationsPickerData[row];
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
_locationTextField.text = _locationsPickerData[row];
}
How to launch picker view manually from code?
UPDATED
if call becomeFirstResponder for textField - following error appears (app crashes):
*** Assertion failure in void _UIPerformResizeOfTextViewForTextContainer(NSLayoutManager *, UIView<NSTextContainerView> *, NSTextContainer *, NSUInteger)(), /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIFoundation/UIFoundation-432.1/UIFoundation/TextSystem/NSLayoutManager_Private.m:1551
2016-04-15 20:01:10.587 Weather-My-Way[5909:2305576] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Only run on the main thread!'
*** First throw call stack:
(0x181d7ee38 0x1813e3f80 0x181d7ed08 0x182704190 0x186df6570 0x186df6250 0x186e28fcc 0x186e4d0a4 0x186e4c7a0 0x186ee44a8 0x186ee3b18 0x186fda090 0x186f5159c 0x186f51a1c 0x186fd8b34 0x1000cdc20 0x1000bae90 0x18236b53c 0x18237e0bc 0x182738510 0x18268a900 0x18267aed8 0x18273a904 0x10018da3c 0x10019a554 0x10019172c 0x10019c66c 0x10019c364 0x1819e1470 0x1819e1020)
libc++abi.dylib: terminating with uncaught exception of type NSException
The error is telling your the problem. You are trying to perform UI tasks on a thread other than the main thread.
Most likely (and correctly) you are downloading the data from the server on a background thread. That's good.
The problem is that you probably also attempt to call [_locationTextField becomeFirstResponder];
on that same background thread. That needs to be done on the main thread.
Wrap that line (and any others that also need to be on the main thread) with this:
dispatch_async(dispatch_get_main_queue(), ^{
[_locationTextField becomeFirstResponder];
});