18

我正在尝试使用 UIToolBar 显示 UIPickerView 但出现一些错误。

这是我的代码 -

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

请帮助我。提前谢谢你。

4

6 回答 6

17

我遇到了同样的问题,从iOS7.03开始出现了一些崩溃。它可以通过 [self.view addSubview:picker];在你的例程结束时移动来解决,基本上是在设置选择器的框架之后。IE picker.frame = datePickerTargetFrame;

[self.view addSubview:picker];必须在所有选择器操作后添加

于 2013-11-04T23:36:13.530 回答
5

我使用 UIDatePicker 作为 inputView,所以 Tao-Nhan 接受的答案对我不起作用。我已经为这个错误苦苦挣扎了很长时间,但今天我终于找到了一个优雅的解决方法!

经过大量调查,我发现崩溃发生在输入视图上调用 didMoveToSuperview 之后。诀窍是使用带有 UIDatePicker 的“包装器”视图作为 inputView 的子视图,并在从 superview 中删除 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。GCD 函数用于在崩溃发生后将dispatch_asyncdatePicker 放回原处。

然后,您可以像这样使用此 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。

于 2016-06-24T14:39:47.630 回答
4

我遇到了类似的问题,我必须更改maximumDateand minimumDateonUIDatePicker那是我inputView的多个UITextFields之一的子视图UITableView,经过大量跟踪后,问题似乎是同时设置了两个日期。我能够使其正常工作的唯一方法是UIDatePicker从我的自定义输入视图中完全删除并创建并将其重新添加并设置新的最小和最大日期值。这是我在相当长的一段时间内被迫做的最丑陋的事情。

于 2016-02-15T12:55:38.740 回答
3

UIDatePicker 在内部管理一个 UIPicker。因此,消息中包含 UIPicker。现在来看实际的错误消息:尝试显示 DatePicker 时是否有足够的空间?它会引发此错误的原因之一是如果找不到足够的空间来显示整个视图。

于 2013-10-14T19:13:56.623 回答
2

自定义 UITableViewCell 中的 UIPickerView 有同样的问题。我已经移动了所有处理在父视图上放置 Picker 视图的逻辑以及它的约束设置- (void)layoutSubviews

更新后它看起来像下一个方式:

- (void)layoutSubviews
{
    [super layoutSubviews];
    [self addSubview:YOUR_PICKER_VIEW]; //'self' in my case was UITableViewCell
    [self addConstraints:PICKER_VIEW_CONSTRAINTS];
}
于 2015-07-06T10:47:10.713 回答
0

我有类似的崩溃。我将代码放入 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];
    }
});
于 2017-09-25T06:29:27.740 回答