iOS 7 中的自定义 UIPickerView 崩溃

Posted

技术标签:

【中文标题】iOS 7 中的自定义 UIPickerView 崩溃【英文标题】:Custom UIPickerView crash in iOS 7 【发布时间】:2013-11-26 08:33:57 【问题描述】:

我制作了一个Custom UIPickerView with three Components each showing label on Selection Indicator,它在 ios 6 中运行良好。

但我在 iOS 7 中遇到了崩溃。

这是我的代码:

ViewController.h

#define kDaysComponent 0
#define kHoursComponent 1
#define kMinutesComponent 2

#import <UIKit/UIKit.h>
#import "LabeledPickerView.h"

@interface ViewController : UIViewController<UIPickerViewDataSource,UIPickerViewDelegate,UITextFieldDelegate>

    NSMutableArray *arrDays;
    NSMutableArray *arrHours;
    NSMutableArray *arrMinutes;

    LabeledPickerView *timePicker;
    IBOutlet UITextField *txtTimeLimit;


@property(nonatomic, retain) NSMutableArray *arrDays;
@property(nonatomic, retain) NSMutableArray *arrHours;
@property(nonatomic, retain) NSMutableArray *arrMinutes;

ViewController.m

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

@synthesize arrDays;
@synthesize arrHours;
@synthesize arrMinutes;

- (void)viewDidLoad


    self.arrDays = [[NSMutableArray alloc]initWithCapacity:100];
    for (NSInteger i = 0; i < 100; i++)
        [arrDays addObject:[NSString stringWithFormat:@"%d",i]];
    
    //self.arrDays = arrDays;
    self.arrHours = [[NSMutableArray alloc]initWithCapacity:24];
    for (NSInteger i = 0; i < 24; i++)
        [arrHours addObject:[NSString stringWithFormat:@"%d",i]];
    
    //self.arrHours = arrHours;
    self.arrMinutes = [[NSMutableArray alloc]initWithCapacity:60];
    for (NSInteger i = 0; i < 60; i++)
        [arrMinutes addObject:[NSString stringWithFormat:@"%d",i]];
    
    //self.arrMinutes = arrMinutes;

    [self.navigationController setNavigationBarHidden:YES];

    [super viewDidLoad];




-(IBAction)Click:(id)sender

    timePicker = [[LabeledPickerView alloc] init];
    timePicker.showsSelectionIndicator = YES;
    timePicker.dataSource = self;
    timePicker.delegate = self;
    [timePicker addLabel:@"Days" forComponent:kDaysComponent forLongestString:@"Hours"];
    [timePicker addLabel:@"Hours" forComponent:kHoursComponent forLongestString:@"Hours"];
    [timePicker addLabel:@"Mins" forComponent:kMinutesComponent forLongestString:@"Mins"];

    UIToolbar* toolbar = [[UIToolbar alloc] init];
    toolbar.barStyle = UIBarStyleBlackTranslucent;
    [toolbar sizeToFit];

    //to make the done button aligned to the right
    UIBarButtonItem *flexibleSpaceLeft = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
    UIBarButtonItem *flexibleSpaceRight = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];

    UIBarButtonItem* doneButton = [[UIBarButtonItem alloc] initWithTitle:@"Done" style:UIBarButtonItemStyleDone target:self action:@selector(doneClicked:)];


    UIBarButtonItem *unlimitedButton = [[UIBarButtonItem alloc] initWithTitle:@"Unlimited" style:UIBarButtonItemStyleBordered target:self action:@selector(unlimitedClicked:)];

    [unlimitedButton setTintColor:[UIColor colorWithRed:100.0f/255.0f green:197.0f/255.0f blue:84.0f/255.0f alpha:1.0f]];

    UIBarButtonItem *cancelButton = [[UIBarButtonItem alloc] initWithTitle:@"Cancel" style:UIBarButtonItemStyleDone target:self action:@selector(cancelClicked:)];

    [toolbar setItems:[NSArray arrayWithObjects:cancelButton,flexibleSpaceLeft,unlimitedButton,flexibleSpaceRight,doneButton, nil]];

    //custom input view
    txtTimeLimit.inputView = timePicker;
    txtTimeLimit.inputAccessoryView = toolbar;

-(void)doneClicked:(id) sender

    [txtTimeLimit resignFirstResponder]; //hides the pickerView

    NSInteger daysRow = [timePicker selectedRowInComponent: kDaysComponent];
    NSInteger hoursRow = [timePicker selectedRowInComponent: kHoursComponent];
    NSInteger minutesRow = [timePicker selectedRowInComponent: kMinutesComponent];
    NSString *days = [arrDays objectAtIndex:daysRow];
    NSString *hours = [arrHours objectAtIndex:hoursRow];
    NSString *minutes = [arrMinutes objectAtIndex:minutesRow];

    txtTimeLimit.text = [[NSString alloc] initWithFormat:
                         @"Expires in [%@] Days [%@] Hours [%@] Minutes.",days,hours,minutes];
    if ([txtTimeLimit.text isEqualToString:@""])
    

    
    else
    

    


-(void)cancelClicked:(id) sender

    [txtTimeLimit resignFirstResponder]; //hides the pickerView


-(void)unlimitedClicked:(id) sender

    [txtTimeLimit resignFirstResponder]; //hides the pickerView
    txtTimeLimit.text = @"Select Time Limit";

- (void)didReceiveMemoryWarning

    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.


#pragma mark Picker View Delegate

- (NSInteger)numberOfComponentsInPickerView:(LabeledPickerView *)pickerView

    return 3;


- (NSInteger)pickerView:(LabeledPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component

    if (component == kDaysComponent)
    
        return [self.arrDays count];
    
    else if (component == kHoursComponent)
    
        return [self.arrHours count];
    
    else if (component == kMinutesComponent)
    
        return [self.arrMinutes count];
    
    return 0;


- (NSString *)pickerView:(LabeledPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component

    if (component == kDaysComponent)
    
        NSLog(@"%@",[arrDays objectAtIndex:row]);
        return [self.arrDays objectAtIndex:row];
    
    else if (component == kHoursComponent)
    
        NSLog(@"%@",[arrHours objectAtIndex:row]);
        return [self.arrHours objectAtIndex:row];
    
    else if (component == kMinutesComponent)
    
        return [self.arrMinutes objectAtIndex:row];
    
    return 0;



#pragma mark TEXT FIELD DELEGATE

- (BOOL)textFieldShouldBeginEditing:(UITextField *)aTextField

    [self Click:aTextField];
    return YES;


我将UIPickerView 显示为UITextField 的输入视图,并且每次我仅在iOS 7 中收到此错误:

Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 5 beyond bounds [0 .. 2]'

我不知道它有什么问题。谁能帮我解决这个问题?

【问题讨论】:

你在哪一行/方法上遇到了崩溃? 在委托方法pickerView titleForRow 代码看起来不错。我唯一的猜测是您在某个时候从数组中删除对象(或将数组重新设置为其他内容),但我在代码中的任何地方都看不到。 我没有从数组中删除对象,我已经发布了整个代码,如您所见。我现在被这个问题困住了。 嗯.. 显然某处缺少某些东西(根据您的代码,您的所有数组都应该有超过 24 个项目)。如果您希望人们能够帮助您,您需要提供更多信息。首先给出导致崩溃的确切代码行。放置一个NSLog 或一个断点,并在崩溃之前查看崩溃数组的内容。没有更多信息,我们只能猜测。 【参考方案1】:

你的崩溃告诉你问题是什么:

-[__NSArrayM objectAtIndex:]: index 5 beyond bounds [0 .. 2]'

当您的数组仅包含 3 个对象时,您试图在索引 5 处获取对象的值。

放置一个断点并检查数组是否包含您所期望的以及组件值是否符合您的期望。

【讨论】:

你的权利...顺便发现了崩溃...但仍然想知道为什么它在 iOS 6 中没有发生! 阿杰,你找到解决办法了吗?【参考方案2】:

请在延迟一秒后尝试设置 txtTimeLimit.inputView。

[self performSelector:@selector(setInputView:) withObject:timePicker afterDelay:1];


- (void)setInputView:(LabeledPickerView*)picker 
   txtTimeLimit.inputView = picker;

我认为这与动画有关....

【讨论】:

【参考方案3】:

你必须关心几件事,

首先是委托和数据源方法。 如果您收到有关委托和数据源的警告,请像这样更正代码

timePicker.dataSource = (id)self;
timePicker.delegate = (id)self;

然后检查数组。希望它能解决您的问题。

【讨论】:

谢谢,但仍然无法正常工作。我已经明确表示,我只在 iOS 7 中遇到此错误。它在 iOS 6 上工作正常 @Ajay 请访问此链接 ..***.com/questions/19125057/… 检查了您的链接,但无论如何它与我的问题无关。他们正在谈论将选择器放入操作表中。但是我通过继承标准 UIPickerView 来制作我的自定义选择器。

以上是关于iOS 7 中的自定义 UIPickerView 崩溃的主要内容,如果未能解决你的问题,请参考以下文章

在 iOS 7 中重用 UIPickerView 中的视图

iOs5,试图了解 UIPickerView 以及如何将其连接到我的自定义类

如何与 Xamarin UITest 中的自定义键盘进行交互?

带有图像的自定义 UIPickerView 皮肤

如何在iOS 7中更改UIPickerView中的文本字体?

UIPickerView 的自定义外观;