Ошибка утверждения в -[UIPickerTableView createPreparedCellForGlobalRow: withIndexPath:], / SourceCache / UIKit Sim/UIKit-2903.2/UITableView.м: 7768
Я пытаюсь показать UIPickerView с помощью UIToolBar, но получаю некоторую ошибку.
Вот мой код -
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];
Получение ошибки на этой строке -
picker.frame = datePickerTargetFrame;
Это ошибка -
*** 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
Пожалуйста, помогите мне.Заранее спасибо.
6 ответов:
У меня была та же проблема, это какой-то сбой, который появился, начиная с iOS7.03. Она может быть решена путем перемещения
[self.view addSubview:picker];
в конце вашей рутины, в основном после установки рамки выбора. т.е.picker.frame = datePickerTargetFrame;
[self.view addSubview:picker];
должны быть добавлены после всех манипуляций сборщиков
Я использую UIDatePicker в качестве inputView, поэтому принятый ответ от Tao-Nhan не сработал для меня. Я долго боролся с этим недугом, но сегодня наконец-то нашел изящный обходной путь!
После долгих исследований я обнаружил, что сбой происходит сразу после вызова didMoveToSuperview на входном представлении. Хитрость заключается в том, чтобы использовать представление "обертки" с UIDatePicker в качестве подвида в качестве inputView и удалить средство выбора так же, как inputView удаляется из superview, и повторно добавить его при следующем запуске на runloop после того, как он будет перемещен в новый superview. Если это звучит слишком запутанно, просто используйте приведенный ниже код в качестве входного представления, и все будет в порядке.
TL; DR, использующий UIDatePicker в качестве inputView? Вот обходной путь, который я нашел:
GSDatePickerInputView.h :
#import <UIKit/UIKit.h> @interface GSDatePickerInputView : UIView @property (nonatomic, readonly) UIDatePicker *datePicker; @property (nonatomic) BOOL useWorkaroundToAvoidCrash; @end
GSDatePickerInputView.М :
Ключевыми элементами являются методы#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
willMoveToSuperview:
иdidMoveToSuperview
. Функцияdispatch_async
GCD используется, чтобы вернуть datePicker после произошла бы авария.Затем вы можете использовать экземпляр этого inputView следующим образом:
GSDatePickerInputView *dateInputView = [[GSDatePickerInputView alloc] init]; dateInputView.useWorkaroundToAvoidCrash = YES; [dateInputView.datePicker addTarget:self action:@selector(datePickerChanged:) forControlEvents:UIControlEventValueChanged]; yourView.inputView = dateInputView;
И вы можете получить доступ к самому datePicker позже, используя этот код:
((GSDatePickerInputView *)yourView.inputView).datePicker
Последнее замечание-свойство
useWorkaroundToAvoidCrash
существует для случаев, когда в одном месте он разбился, но в другом месте его не было (что случилось со мной). Очевидно, что лучше избегать такой халтуры, когда это возможно, поэтому только установите это свойство в YES в тех местах, где оно на самом деле обрушивающийся.
У меня была аналогичная проблема, когда я должен был изменить
maximumDate
иminimumDate
наUIDatePicker
, что было подвидомinputView
на одном из многихUITextField
s в моемUITableView
, после Большого отслеживания оказалось, что проблема заключалась в установке обеих дат одновременно. Единственный способ, которым я смог получить эту работу, - это полностью удалитьUIDatePicker
из моего пользовательского представления ввода, создать и добавить его обратно и установить новые значения даты min и max. Это самая уродливая вещь, которую я был вынужден сделать в довольно некоторых время.
UIDatePicker управляет UIPicker внутренне. Итак, сообщение содержит UIPicker в нем. Теперь к фактическому сообщению об ошибке: Есть ли у вас достаточно места, когда вы пытаетесь показать DatePicker? Одна из причин, по которой он выбросит эту ошибку, заключается в том, что не удалось найти достаточно недвижимости, чтобы отобразить весь вид.
Есть та же проблема с UIPickerView в пользовательском UITableViewCell. Я переместил всю логику, которая имела дело с размещением вида выбора на родительском виде плюс настройки его ограничений на
- (void)layoutSubviews
После обновления это выглядело следующим образом:
- (void)layoutSubviews { [super layoutSubviews]; [self addSubview:YOUR_PICKER_VIEW]; //'self' in my case was UITableViewCell [self addConstraints:PICKER_VIEW_CONSTRAINTS]; }
У меня была похожая авария. Я ввел свой код в dispatch_after и сбой разрешился.
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]; } });