Frage

I had made a Custom UIPickerView with three Components each showing label on Selection Indicator which is working fine in iOS 6.

But I am getting a crash in iOS 7.

Here is my code:

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;

}

I am showing UIPickerView as an input view for UITextField and each time I am getting this error in iOS 7 only:

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

I don't know what's wrong with it. Can anyone please help me on this?

War es hilfreich?

Lösung

Your crash is telling you what the problem is:

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

You are trying to get a value of object at the index 5 when your array only contains 3 objects.

Put a break point in and check the arrays contain what you expect and the component value is what you expect.

Andere Tipps

Please try to set txtTimeLimit.inputView after delays like one second.

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


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

I think it's something doing with the animation....

You have to concern in few things,

First is the delegate and datasource method. If u get the warning on delegate and datasource then correct the code like this

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

Then Check the array. Hopefully it will solve your problem.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top