I am trying to show UIPickerView with UIToolBar but getting some error.
Here is my code -
CGRect toolbarTargetFrame = CGRectMake(0, self.view.bounds.size.height-216-44, 320, 44);
CGRect datePickerTargetFrame = CGRectMake(0, self.view.bounds.size.height-216, 320, 216);
UIView *darkView = [[UIView alloc] initWithFrame:self.view.bounds];
darkView.alpha = 0;
darkView.backgroundColor = [UIColor blackColor];
darkView.tag = 9;
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissDatePicker:)];
[darkView addGestureRecognizer:tapGesture];
[self.view addSubview:darkView];
UIDatePicker *picker = [[UIDatePicker alloc] init];
picker.autoresizingMask = UIViewAutoresizingFlexibleWidth;
picker.datePickerMode = UIDatePickerModeDate;
[picker addTarget:self action:@selector(dueDateChanged:) forControlEvents:UIControlEventValueChanged];
[picker setFrame:CGRectMake(0,235,320,120)];
picker.backgroundColor = [UIColor blackColor];
[self.view addSubview:picker];
UIToolbar *toolBar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, self.view.bounds.size.height, 320, 44)];
toolBar.tag = 11;
toolBar.barStyle = UIBarStyleBlackTranslucent;
UIBarButtonItem *spacer = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil] ;
UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(dismissDatePicker:)];
[toolBar setItems:@[spacer, doneButton]];
[self.view addSubview:toolBar];
[UIView beginAnimations:@"MoveIn" context:nil];
toolBar.frame = toolbarTargetFrame;
picker.frame = datePickerTargetFrame;
darkView.alpha = 0.5;
[UIView commitAnimations];
Getting error on this line -
picker.frame = datePickerTargetFrame;
This is Error -
*** Assertion failure in -[UIPickerTableView _createPreparedCellForGlobalRow:withIndexPath:], /SourceCache/UIKit_Sim/UIKit-2903.2/UITableView.m:7768
2013-10-03 13:43:12.688 Mistoh Beta 1[7228:a0b] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UITableView dataSource is not set'
libc++abi.dylib: terminating with uncaught exception of type NSException
Please Help me.Thank you in advance.
I had the same problem, it's some crash that appeared starting at iOS7.03.
It can be solved by moving
[self.view addSubview:picker];
at the end of your routine, basically after setting picker's frame. i.e.
picker.frame = datePickerTargetFrame;
[self.view addSubview:picker];
must be added after all pickers manipulations
I am using UIDatePicker as inputView so the accepted answer from Tao-Nhan didn't work for me. I've been struggling with this bug for a long time, but today I finally found an elegant work-around!
After much investigation, I found out that the crash occurs just after didMoveToSuperview is called on the input view. The trick is to use a 'wrapper' view with UIDatePicker as a subview as the inputView, and to remove the picker just as the inputView is being removed from superview, and to re-add it on the next run on runloop after it's moved to a new superview. If that sounds too confusing, just use the code below as your input view and you'll be fine.
TL;DR Using UIDatePicker as inputView? Here is the workaround that I found:
GSDatePickerInputView.h:
#import <UIKit/UIKit.h>
@interface GSDatePickerInputView : UIView
@property (nonatomic, readonly) UIDatePicker *datePicker;
@property (nonatomic) BOOL useWorkaroundToAvoidCrash;
@end
GSDatePickerInputView.m:
#import "GSDatePickerInputView.h"
@interface GSDatePickerInputView ()
@property (nonatomic, strong, readwrite) UIDatePicker *datePicker;
@end
@implementation GSDatePickerInputView
- (instancetype)init {
if (self = [super initWithFrame:CGRectMake(0, 0, 320, 166)]) {
self.translatesAutoresizingMaskIntoConstraints = NO;
self.backgroundColor = [UIColor whiteColor];
UIDatePicker *datePicker = [[UIDatePicker alloc] init];
datePicker.calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierISO8601];
datePicker.backgroundColor = [UIColor whiteColor];
[self addSubview:datePicker];
self.datePicker = datePicker;
}
return self;
}
- (void)layoutSubviews {
[super layoutSubviews];
self.datePicker.frame = self.bounds;
}
- (void)willMoveToSuperview:(UIView *)newSuperview {
if (self.useWorkaroundToAvoidCrash == YES) {
if (newSuperview == nil) {
[self.datePicker removeFromSuperview];
}
}
}
- (void)didMoveToSuperview {
if (self.useWorkaroundToAvoidCrash == YES) {
if (self.superview != nil) {
dispatch_async(dispatch_get_main_queue(), ^{
[self addSubview:self.datePicker];
self.datePicker.frame = self.bounds;
});
}
}
}
@end
The key pieces are the methods willMoveToSuperview:
and didMoveToSuperview
. The dispatch_async
GCD function is used to put the datePicker back after the crash would've occurred.
You can then use an instance of this inputView like this:
GSDatePickerInputView *dateInputView = [[GSDatePickerInputView alloc] init];
dateInputView.useWorkaroundToAvoidCrash = YES;
[dateInputView.datePicker addTarget:self action:@selector(datePickerChanged:) forControlEvents:UIControlEventValueChanged];
yourView.inputView = dateInputView;
And you can access the datePicker itself later using this code:
((GSDatePickerInputView *)yourView.inputView).datePicker
One last note - the property useWorkaroundToAvoidCrash
is there for cases when in one place it was crashing but in another place it wasn't (which happened to me). It's obviously better to avoid such hackery whenever possible, so only set this property to YES in places where it's actually crashing.
I've had a similar problem where I had to change the maximumDate
and minimumDate
on UIDatePicker
that was a subview of an inputView
on one of many UITextField
s in my UITableView
, after a lot of tracking it appeared that the problem was setting both dates at the same time. The only way I was able to get this working is by removing the UIDatePicker
from my custom input view entirely and creating and adding it back in and setting the new min and max date values. This is the ugliest thing I was forced to do in quite some time.
UIDatePicker manages a UIPicker internally. So, the message contains UIPicker in it.
Now to the actual error message:
Do you have enough room when you are trying to show the DatePicker?
One of the reason it will throw this error is if could not find enough real estate to display the entire view.
Have the same problem with UIPickerView in a custom UITableViewCell. I have moved all logic that had dealt with placing of the Picker view on the parent view plus settings it's constraints to - (void)layoutSubviews
After updates it looked like the next way:
- (void)layoutSubviews
{
[super layoutSubviews];
[self addSubview:YOUR_PICKER_VIEW]; //'self' in my case was UITableViewCell
[self addConstraints:PICKER_VIEW_CONSTRAINTS];
}
I had similar crash. I put my code in dispatch_after and crash resolved.
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(.4 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
if (textField == _txtFieldEndDate)
{
_datePicker.maximumDate = [NSDate dateWithDaysFromNow:100 * 365];
[_datePicker setDate:[NSDate date]];
}
else if (textField == _txtFieldStrtDate)
{
_datePicker.maximumDate = [NSDate date];
}
});