ios - how - text field with uipickerview
Error de aserciĆ³n en-[UIPickerTableView_createPreparedCellForGlobalRow: withIndexPath:],/SourceCache/UIKit_Sim/UIKit-2903.2/UITableView.m:7768 (6)
Estoy intentando mostrar UIPickerView con UIToolBar pero obtengo un error.
Aquí está mi código -
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];
Obteniendo error en esta línea -
picker.frame = datePickerTargetFrame;
Esto es 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
Por favor ayúdame. Gracias de antemano.
Estoy usando UIDatePicker como inputView, por lo que la respuesta aceptada de Tao-Nhan no me funcionó. He estado luchando contra este error durante mucho tiempo, ¡pero hoy finalmente encontré una solución elegante!
Después de mucha investigación, descubrí que el bloqueo se produce justo después de llamar a didMoveToSuperview en la vista de entrada. El truco consiste en utilizar una vista de "envoltorio" con UIDatePicker como una subvista como inputView, y eliminar el selector justo cuando el inputView se está eliminando de superview, y volver a agregarlo en la próxima ejecución en runloop después de moverlo una nueva supervisión. Si eso suena demasiado confuso, solo use el código a continuación como su vista de entrada y estará bien.
TL; DR utilizando UIDatePicker como inputView? Aquí está la solución que encontré:
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
Las piezas clave son los métodos willMoveToSuperview:
y didMoveToSuperview
. La función dispatch_async
GCD se utiliza para devolver el datePicker después de que se produjera el bloqueo.
Entonces puedes usar una instancia de este inputView como este:
GSDatePickerInputView *dateInputView = [[GSDatePickerInputView alloc] init];
dateInputView.useWorkaroundToAvoidCrash = YES;
[dateInputView.datePicker addTarget:self action:@selector(datePickerChanged:) forControlEvents:UIControlEventValueChanged];
yourView.inputView = dateInputView;
Y puede acceder al datePicker en sí más adelante usando este código:
((GSDatePickerInputView *)yourView.inputView).datePicker
Una última nota: la propiedad useWorkaroundToAvoidCrash
está ahí para los casos en que en un lugar se estrelló pero en otro lugar no (lo que me ocurrió a mí). Obviamente, es mejor evitar este tipo de piratería siempre que sea posible, así que solo establezca esta propiedad en SÍ en los lugares donde realmente se está estrellando.
He tenido un problema similar en el que tuve que cambiar la minimumDate
maximumDate
y la minimumDate
en UIDatePicker
que era una subvista de una entrada inputView
en uno de los muchos UITextField
s en mi UITableView
, después de mucho seguimiento, parecía que el problema estaba configurando ambas fechas en al mismo tiempo. La única forma en que pude hacer que esto funcionara es eliminando por UIDatePicker
el UIDatePicker
de mi vista de entrada personalizada y creando y agregando de nuevo y configurando los nuevos valores de fecha mínima y máxima. Esta es la cosa más fea que me obligaron a hacer en bastante tiempo.
Tiene el mismo problema con UIPickerView en un UITableViewCell personalizado. He movido toda la lógica que tenía que ver con la colocación de la vista Selector en la vista primaria más la configuración de sus restricciones a - (void)layoutSubviews
Después de las actualizaciones se veía de la siguiente manera:
- (void)layoutSubviews
{
[super layoutSubviews];
[self addSubview:YOUR_PICKER_VIEW]; //''self'' in my case was UITableViewCell
[self addConstraints:PICKER_VIEW_CONSTRAINTS];
}
Tuve el mismo problema, es un error que apareció a partir de iOS7.03. Se puede resolver moviendo [self.view addSubview:picker];
al final de su rutina, básicamente después de configurar el marco del selector. es decir, picker.frame = datePickerTargetFrame;
[self.view addSubview:picker];
Debe ser agregado después de todas las manipulaciones de los recolectores.
Tuve un choque similar. Puse mi código en dispatch_after y resolví el error.
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];
}
});
UIDatePicker gestiona un UIPicker internamente. Por lo tanto, el mensaje contiene UIPicker en él. Ahora, al mensaje de error actual: ¿Tiene suficiente espacio cuando intenta mostrar el Selector de fechas? Una de las razones por las que arrojará este error es si no se pudieron encontrar bienes raíces suficientes para mostrar la vista completa.