Ошибка утверждения в - [UIPickerTableView _createPreparedCellForGlobalRow: withIndexPath:],/SourceCache/UIKit_Sim/UIKit-2903.2/UITableView.m: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
Пожалуйста, помогите мне. Спасибо заранее.
Ответы
Ответ 1
У меня была такая же проблема, это был крах, который появился с iOS7.03.
Его можно решить, перемещая
[self.view addSubview: picker];
в конце вашей процедуры, в основном после
picker.frame = datePickerTargetFrame;
[self.view addSubview: picker]; должен быть добавлен после всех манипуляций с подборщиками
Ответ 2
Я использую UIDatePicker как inputView, поэтому принятый ответ от Tao-Nhan не работал у меня. Я долгое время боролся с этой ошибкой, но сегодня я наконец нашел элегантный обход!
После долгих исследований выяснилось, что авария происходит сразу после вызова didMoveToSuperview в представлении ввода. Фокус в том, чтобы использовать представление "обертка" с UIDatePicker в качестве подзадачи в качестве входного вида и удалить сборщик так же, как inputView будет удален из супервизора, и повторно добавить его в следующий прогон на runloop после его перемещения в новый супервизор. Если это звучит слишком запутанно, просто используйте приведенный ниже код в качестве входного представления, и все будет в порядке.
TL; DR Использование UIDatePicker как inputView? Вот обходной путь, который я нашел:
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
Ключами являются методы willMoveToSuperview:
и didMoveToSuperview
. Функция dispatch_async
GCD используется, чтобы вернуть datePicker после сбоя.
Затем вы можете использовать экземпляр этого вводаView следующим образом:
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 в местах, где он действительно сбой.
Ответ 3
У меня была аналогичная проблема, когда мне пришлось изменить maximumDate
и minimumDate
на UIDatePicker
, который был поднабором inputView
на одном из многих UITextField
в моем UITableView
, после было много отслеживания, что проблема заключалась в установлении обеих дат одновременно. Единственный способ, которым я смог получить эту работу, - это удалить UIDatePicker
из моего пользовательского входа ввода полностью и создать и добавить его обратно и установить новые минимальные и максимальные значения даты. Это самая уродливая вещь, которую я заставил сделать за довольно долгое время.
Ответ 4
UIDatePicker управляет UIPicker внутренне. Таким образом, сообщение содержит UIPicker в нем.
Теперь к фактическому сообщению об ошибке:
У вас достаточно места, когда вы пытаетесь показать DatePicker?
Одна из причин, по которой эта ошибка возникнет, заключается в том, что не удалось найти достаточно недвижимости для отображения всего представления.
Ответ 5
У вас такая же проблема с UIPickerView в пользовательском UITableViewCell. Я переместил всю логику, которая касалась размещения представления Picker на родительском представлении плюс настройки, которые он ограничивает - (void)layoutSubviews
После обновлений это выглядело следующим образом:
- (void)layoutSubviews
{
[super layoutSubviews];
[self addSubview:YOUR_PICKER_VIEW]; //'self' in my case was UITableViewCell
[self addConstraints:PICKER_VIEW_CONSTRAINTS];
}
Ответ 6
У меня был подобный сбой. Я поместил свой код в диспетчеру_а после этого, и авария разрешилась.
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];
}
});