Xcode NSRangeException 在第二次运行代码时

Posted

技术标签:

【中文标题】Xcode NSRangeException 在第二次运行代码时【英文标题】:Xcode NSRangeException on second run through of code 【发布时间】:2013-05-23 14:42:13 【问题描述】:

现在我知道 NSRangeException 是什么了。我不明白为什么在我的代码第一次运行时它很好,但是当第二次设置相同的代码(和变量)时它失败了。即使单步执行代码,我也看不出它与第一次运行的不同之处。

整个代码从我的 php api 获取一组 JSON 值(基本上只是客户信息、预订的单位、日期等)它过去只是在 UITableView 中显示它,我决定按日期对表进行分组它被预订了(在我看来,Apple 应该有更好的方法来做到这一点,也许扩展他们的 UITableView?)

我的.h

    @interface LTBViewController : UIViewController 
IBOutlet UITableView *mainTableView;

NSArray *tickets;  //for storing our serialized JSON
NSMutableData *data; //for appending our JSON as we're getting it
NSString *token; //for security authentication with our custom API


NSMutableArray *days; //for storing any days with bookings retrieved from tickets
NSMutableDictionary *groupedTickets; //for storing tickets to correlate to days
NSArray *filteredArray; //for our finalized output

@end

我的大部分 .m(重要部分)

- (void)viewDidAppear:(BOOL)animated

    [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;

    NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"http://myurl.com/api/api.php?api=%@&function=%@", token, @"active"]];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    [NSURLConnection connectionWithRequest:request delegate:self];



    //[[NSURLConnection alloc] initWithRequest:request delegate:self]; old way of doing it


- (void)viewDidLoad

    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    //initialize from our settings file and make sure we're authenticated
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    token = [defaults objectForKey:@"api_token"];
    NSLog(@"%@",token);

    //initialize our sorting arrays
    days = [[NSMutableArray alloc] init];
    groupedTickets = [[NSMutableDictionary alloc] init];
    filteredArray = [[NSArray  alloc] init];



- (void)groupTable 


    NSUInteger count = 0;
    for (LTBViewController *ticket in tickets)
    

        NSString *date = [[tickets objectAtIndex:count] objectForKey:@"dateIn"];
        if (![days containsObject:date])
        
            [days addObject:date];
            [groupedTickets setObject:[NSMutableArray arrayWithObject:ticket] forKey:date];
        
        else
        
            [((NSMutableArray*)[groupedTickets objectForKey:date]) addObject:ticket];
        
        count +=1;

    
    count = 0;
    [mainTableView reloadData];



//for when we get a response
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response

    data = [[NSMutableData alloc] init];



//for getting data
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)thedata

    [data appendData:(thedata)];




//for when connection finished
- (void)connectionDidFinishLoading:(NSURLConnection *)connection

    tickets = [NSJSONSerialization JSONObjectWithData:data options:NO error:nil];

    [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;

    [self groupTable]; //starts our grouping methods



//for when connection fails
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error

    UIAlertView *errorView = [[UIAlertView alloc] initWithTitle:@"Error" message:@"Could not connect to server" delegate:nil cancelButtonTitle:@"dismiss" otherButtonTitles:nil, nil];
    [errorView show];


//overriding the "delete" text for our UITableView
- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath 
    return @"Close Ticket";


-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section

    NSString *date = [days objectAtIndex:section];
    return date;



- (int)numberOfSectionsInTableView:(UITableView *)tableView

    return [days count];



- (int)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

    NSString *date = [days objectAtIndex:section];
    NSLog(@"%@", date);
    return [[groupedTickets objectForKey:date] count];



- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MainCell"];

    tableView.layer.cornerRadius = 5.0; //rounds our table corners

    if(cell == nil) 
        cell = [[UITableViewCell alloc] initWithStyle:(UITableViewCellStyleSubtitle) reuseIdentifier:@"MainCell"];
    

//I'm sure theres a better way to do this but it works for now

    NSString *date = [days objectAtIndex:[indexPath section]];

    NSPredicate *search = [NSPredicate predicateWithFormat:@"dateIn == %@", date];

    filteredArray = [tickets filteredArrayUsingPredicate:search];

//这就是在索引 1 处第二次失败的原因

cell.textLabel.text = [NSString stringWithFormat:@"%@",[[filteredArray objectAtIndex:[indexPath row]] objectForKey:@"ticketnumber"] ]; 

    cell.detailTextLabel.text = [NSString stringWithFormat:@"%@", [[filteredArray objectAtIndex:[indexPath row]] objectForKey:@"customerName"]];

    return cell;

当单击一个项目时,它会移动到另一个视图控制器(可以正常工作)但是当从它按下后退按钮时,此代码会失败。我会很感激任何额外的眼睛检查它并帮助我找到我的错误。 (或更好的方法)

谢谢!

【问题讨论】:

【参考方案1】:

知道了。我想当我将值重新分配给我的 NSMutableArray 天和 NSMutableDictionary groupedTickets 时,它只会覆盖以前的值。

我在视图上执行的发布将消失,它现在可以工作了。

如果有更好的方法来做到这一点,我会有兴趣学习它。

【讨论】:

以上是关于Xcode NSRangeException 在第二次运行代码时的主要内容,如果未能解决你的问题,请参考以下文章

GHAssertThrowsSpecific 找不到类型 NSRangeException

Xcode异常解释

xcode核心数据部分错误

获取异常'NSRangeException'

iphone dev - 如何捕获异常'NSRangeException'

NSRangeException - 无法移除观察者