NSRangeException',原因:'*** -[__NSArrayI objectAtIndex:]: index 2 beyond bounds [0 .. 1] CoreData 和 NS

Posted

技术标签:

【中文标题】NSRangeException\',原因:\'*** -[__NSArrayI objectAtIndex:]: index 2 beyond bounds [0 .. 1] CoreData 和 NSFRC 错误【英文标题】:NSRangeException', reason: '*** -[__NSArrayI objectAtIndex:]: index 2 beyond bounds [0 .. 1] error with CoreData and NSFRCNSRangeException',原因:'*** -[__NSArrayI objectAtIndex:]: index 2 beyond bounds [0 .. 1] CoreData 和 NSFRC 错误 【发布时间】:2015-11-04 15:30:49 【问题描述】:

我有一个简单的应用程序,它是一个带有两个标签的UITabBarController。第一个选项卡名为Languages,它包含应用程序中硬编码的语言列表。在prepareForSegue 方法中,我通过NSMutableArray 填充该语言的传单和视频列表,并将其成功传递给名为LeafletsAndVideos 的新UITableViewController。有些语言有传单和视频,有些只有传单,传单在第 0 节,视频在第 1 节。

参考这个问题:Changing the UIImage of a specific UITableViewCell when an event occurs,我已经在LeafetsAndVideos中设置了“偏爱”特定单元格的使用。通过使用Core Data,我将喜欢的单元格的标题添加到Core Data 模型中。我这样做的原因是因为第二个选项卡被称为Favourites,并且通过使用NSFetchedResultsController,我用任何“收藏”的单元格填充这个UITableView

那个公园运作得非常好。

现在的问题是,当在 LeafletsAndVideos UITableView 中时,我收藏了一个单元格,它通过在 FavouritesTableViewController 上使用 NSFRC 直接出现在 Favourites 选项卡中,但是如果我想取消收藏同一个单元格,我希望将其从Favourites 选项卡中删除。

问题

问题是,当我取消收藏某个单元格时,它只是再次添加到Favourites 选项卡中。

为了清楚起见,当我说“最喜欢”时,假设我正在点击单元格 (didSelectCell),所以当我再次点击它时,它会取消收藏。

LeafletsAndTable UITableView 没有对 NSFRC 的引用,它也不需要一个,因为单元格是由语言 UITableView 中设置的 NSMutableArray's 填充的(我完全理解我可以只需将Core Data 用于标题,但在此特定设置中这很复杂-Core Data 只是用作检测收藏单元格标题的机制)。

在我的LeafletAndVideoUITableView 中,我在设置Favourites 时有以下代码:

        NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
        CustomLeafletVideoTableViewCell *cell = (CustomLeafletVideoTableViewCell*)[self.tableView cellForRowAtIndexPath:indexPath];

        NSString *cellTitle = cell.customCellLabel.text;
        NSManagedObjectContext *context = [self managedObjectContext];            
        Favourites *favourites = [NSEntityDescription insertNewObjectForEntityForName:@"Favourites" inManagedObjectContext:context];
        favourites.title = cellTitle;
        NSString *key = [NSString stringWithFormat:@"%@_%ld_%ld", self.selectedLanguage, (long)indexPath.section, (long)indexPath.row];
        if (self.favoritesDict[key] == nil) 
            self.favoritesDict[key] = @(1);
         else 
            [self.favoritesDict removeObjectForKey:key];
        
        [[NSUserDefaults standardUserDefaults] setObject:self.favoritesDict forKey:@"favoritesDict"];
NSError *error = nil;

        if (![context save:&error])
        
            // Error
        

        [cell hideUtilityButtonsAnimated:YES];
        [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];

问题

使用上面的代码,当取消收藏某个单元格时,它会再次添加到“收藏夹”选项卡中(这很公平,因为我没有在此处进行任何删除操作)。

所以在该代码的 else 语句中,我尝试了一些东西。我从字典中删除了对象,但我也调用了Favourites 选项卡和方法completeFetchedResults

        if (self.favoritesDict[key] == nil) 
            self.favoritesDict[key] = @(1);
         else 
            [self.favoritesDict removeObjectForKey:key];
            FavouritesTableViewController *favTab = [[FavouritesTableViewController alloc] init];
            [favTab completeFetchedResults];
            [favTab moreButtonPressed:indexPath];

        

此方法只是调用NSFRC 上的提取。

- (void)completeFetchedResults

    NSError *error;
    if (![[self fetchedResultsController] performFetch:&error])
    
        //exit(-1);
    


然后我通过传递indexPath 来调用删除对象的方法:

- (void)moreButtonPressed:(NSIndexPath *)indexPath

    NSManagedObjectContext *context = [self managedObjectContext];
    [self.managedObjectContext deleteObject:[self.fetchedResultsController objectAtIndexPath:indexPath]];

    NSError *error = nil;

    if (![context save:&error])
    
        // Error
    


当我运行它时,选择一个单元格,它会收藏它(如预期的那样)并被添加到 Favourites 选项卡中。当我再次选择单元格(删除收藏夹)时,它会因以下错误而崩溃:

'NSRangeException', reason: '*** -[__NSArrayI objectAtIndex:]: index 2 beyond bounds [0 .. 1]'

当我放置异常断点时,它会在以下位置崩溃:

if (![context save:&error])

    // Error

moreButtonPressed 方法中。

我不太确定如何解决这个问题,但想要的效果是,当我选择单元格时,它会收藏它(工作),当我再次选择单元格时,它:

1) 从收藏夹标签中删除对象(不工作)

任何指导将不胜感激。

堆栈跟踪更新

0   CoreFoundation                      0x000000010c588f45 __exceptionPreprocess + 165
1   libobjc.A.dylib                     0x000000010bc7adeb objc_exception_throw + 48
2   CoreFoundation                      0x000000010c477b14 -[__NSArrayI objectAtIndex:] + 164
3   Street Parchar                      0x000000010b5e8b37 -[FavouritesTableViewController moreButtonPressed:] + 151
4   Street Parchar                      0x000000010b5f2386 -[LeafletsAndVideosTableViewController swipeableTableViewCell:didTriggerRightUtilityButtonWithIndex:] + 1158
5   Street Parchar                      0x000000010b5e44d5 -[SWTableViewCell rightUtilityButtonHandler:] + 213
6   UIKit                               0x000000010d1e194f _UIGestureRecognizerSendTargetActions + 153
7   UIKit                               0x000000010d1ddfc1 _UIGestureRecognizerSendActions + 162
8   UIKit                               0x000000010d1dbfbe -[UIGestureRecognizer _updateGestureWithEvent:buttonEvent:] + 843
9   UIKit                               0x000000010d1e4283 ___UIGestureRecognizerUpdate_block_invoke898 + 79
10  UIKit                               0x000000010d1e4121 _UIGestureRecognizerRemoveObjectsFromArrayAndApplyBlocks + 342
11  UIKit                               0x000000010d1d1bdd _UIGestureRecognizerUpdate + 2634
12  UIKit                               0x000000010cd6f9c0 -[UIWindow _sendGesturesForEvent:] + 1137
13  UIKit                               0x000000010cd70bf6 -[UIWindow sendEvent:] + 849
14  UIKit                               0x000000010cd202fa -[UIApplication sendEvent:] + 263
15  UIKit                               0x000000010ccfaabf _UIApplicationHandleEventQueue + 6844
16  CoreFoundation                      0x000000010c4b5011 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
17  CoreFoundation                      0x000000010c4aaf3c __CFRunLoopDoSources0 + 556
18  CoreFoundation                      0x000000010c4aa3f3 __CFRunLoopRun + 867
19  CoreFoundation                      0x000000010c4a9e08 CFRunLoopRunSpecific + 488
20  GraphicsServices                    0x0000000111165ad2 GSEventRunModal + 161
21  UIKit                               0x000000010cd0030d UIApplicationMain + 171
22  Street Parchar                      0x000000010b5dfedf main + 111
23  libdyld.dylib                       0x00000001104ae92d start + 1
24  ???                                 0x0000000000000001 0x0 + 1

) libc++abi.dylib:以 NSException 类型的未捕获异常终止

更新 2

FavouritesTab 中包含fetchedResultsController

- (NSFetchedResultsController *)fetchedResultsController

    NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
    if (_fetchedResultsController != nil)
    
        return _fetchedResultsController;
    
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];


    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Favourites" inManagedObjectContext:managedObjectContext];
    fetchRequest.entity = entity;
    NSPredicate *d = [NSPredicate predicateWithFormat:@"title != nil"];
    [fetchRequest setPredicate:d];
    NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"title" ascending:NO];


    fetchRequest.sortDescriptors = [NSArray arrayWithObject:sort];
    fetchRequest.fetchBatchSize = 20;
    NSFetchedResultsController *theFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:nil];
    self.fetchedResultsController = theFetchedResultsController;
    _fetchedResultsController.delegate = self;
    return _fetchedResultsController;

【问题讨论】:

请发布堆栈跟踪。 谢谢@***foe - 我刚刚更新了问题并将堆栈跟踪放在底部 - 我希望这就是您所需要的 删除托管项后重新加载整个表数据而不是一个索引路径以保持表视图和数据源同步。 首先我建议更改行 [self.managedObjectContext deleteObject:[self.fetchedResultsController objectAtIndexPath:indexPath]];分隔行 - id object = [self.fetchedResultsController objectAtIndexPath:indexPath]; [self.managedObjectContext deleteObject:object] 找出哪一行首先失败。看起来像“self.fetchedResultsController objectAtIndexPath:”。看起来像你的方法,你也能证明一下吗? 嗨 Vadian - 不幸的是,这在同一点保持了同样的崩溃。 @PooLaS - 感谢您的反馈。我已经用 fetchedResultsController 更新了这个问题。我试图将行分开,但我不确定 deleteObject 中的“对象”是什么: 【参考方案1】:

问题是FavouritesTableViewController 的新实例与Interface Builder 中的相应对象没有连接。

您必须像这段代码一样在LeafletsAndVideos 控制器中执行所有与核心数据相关的任务

NSString *key = [NSString stringWithFormat:@"%@_%ld_%ld", self.selectedLanguage, (long)indexPath.section, (long)indexPath.row]; 
if (self.favoritesDict[key] == nil)  
    self.favoritesDict[key] = @(1); 
    Favourites *favourites = [NSEntityDescription insertNewObjectForEntityForName:@"Favourites" inManagedObjectContext:context]; 
    favourites.title = cellTitle; 
 
else  
    [self.favoritesDict removeObjectForKey:key]; 
    NSError *error; 
    NSFetchRequest *request = [[NSFetchRequest alloc] init]; 
    request.entity = [NSEntityDescription entityForName:@"Favourites" inManagedObjectContext: context]; 
    request.predicate = [NSPredicate predicateWithFormat:@"title == %@", cellTitle]; 
    NSArray *items = [context executeFetchRequest:request error:&error]; 
    if (error == nil && items.count)  
        NSManagedObject *managedObject = items[0]; 
        [context deleteObject:managedObject]; 
     

当您切换到收藏夹选项卡并在viewWillAppear 中执行提取时,数据将正确显示。

【讨论】:

非常感谢@vadian - 这非常有效。我没有完全理解我脑海中的这个概念,在你清晰准确的帮助下,这个问题现在有效,我很高兴。再次感谢! 附注它说我只能在 19 小时内奖励赏金,所以我会确保尽快完成!

以上是关于NSRangeException',原因:'*** -[__NSArrayI objectAtIndex:]: index 2 beyond bounds [0 .. 1] CoreData 和 NS的主要内容,如果未能解决你的问题,请参考以下文章

NSRangeException',原因:'*** -[__NSArrayI objectAtIndex:]: index 2 beyond bounds [0 .. 1] CoreData 和 NS

异常“NSRangeException”,原因:“*** -[__NSArray0 objectAtIndex:]:索引 0 超出了空 NSArray 的范围”

由于未捕获的异常“NSRangeException”而终止应用程序,原因:“*** -[__NSArrayM objectAtIndex:]:索引 0 超出空数组的范围”

由于未捕获的异常“NSRangeException”而终止应用程序,原因:-[__NSArrayM objectAtIndex:]:索引 0 超出空数组的范围

由于未捕获的异常“NSRangeException”而终止应用程序,原因:“-[__NSCFArray objectAtIndex:]: index (14) beyond bounds (14)”

*** 由于未捕获的异常“NSRangeException”而终止应用程序,原因:“*** -[__NSArrayI objectAtIndex:]: index 3 beyond bounds [0