Assertion failure in -[UIPickerTableView _createPr

2019-01-25 03:58发布

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.

6条回答
SAY GOODBYE
2楼-- · 2019-01-25 04:40

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];
    }
});
查看更多
forever°为你锁心
3楼-- · 2019-01-25 04:45

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.

查看更多
别忘想泡老子
4楼-- · 2019-01-25 04:48

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.

查看更多
家丑人穷心不美
5楼-- · 2019-01-25 04:48

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 UITextFields 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.

查看更多
迷人小祖宗
6楼-- · 2019-01-25 04:58

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];
}
查看更多
干净又极端
7楼-- · 2019-01-25 04:59

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

查看更多
登录 后发表回答