NSRangeException',原因:' *** - [__ NSArrayI objectAtIndex:]:索引2超出了与CoreData和NSFRC

时间:2015-11-04 15:30:50

标签: ios objective-c uitableview core-data nsfetchedresultscontroller

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

参考这个问题:Changing the UIImage of a specific UITableViewCell when an event occurs,我已经设置了使用" Favourting" LeafetsAndVideos中的特定单元格。通过使用Core Data,我获取了受欢迎的单元格的标题,并将其添加到Core Data模型中。我这样做的原因是因为第二个标签名为Favourites,并且通过使用NSFetchedResultsController,我正在填充此UITableView以及任何已经" Favourited&#34的单元格;。

该公园运作良好。

现在的问题是,在LeafletsAndVideos UITableView中,我最喜欢的是一个单元格,它会立即出现在Favourites标签中,通过在{{1}上使用NSFRC但是,如果我想要不同于同一个单元格,我希望从FavouritesTableViewController标签中删除它。

问题

问题在于,当我不喜欢单元格时,它会再次添加到Favourites标签中。

为了清楚起见,当我说"收藏"时,让我们说我正在点击单元格(Favourites),所以当我再次点击它时,它unfavorites。

didSelectCell LeafletsAndTable没有引用UITableView,并且它并不真正需要一个,因为单元格正由NSFRC设置填充语言NSMutableArray's(我完全理解我可以使用UITableView作为标题,但在此特定设置中这很复杂 - Core Data仅用作检测最喜欢的细胞的标题)。

在我的Core Data LeafletAndVideo中,我在设置UITableView时有以下代码:

Favourites

问题

使用上面的代码,当不喜欢一个单元格时,它会再次添加到“收藏夹”选项卡(这很公平,因为我没有在这里删除任何内容)。

所以在该代码的else语句中,我尝试了一些东西。我从字典中删除了该对象,但我也在调用 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]; 标签和方法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]; } 上调用fetch。

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 } 方法中。

我不太清楚如何解决这个问题,但是当我选择单元格时,它会收藏它(工作),当我再次选择单元格时,它会:

1)从“收藏夹”选项卡中删除对象(不工作)

任何指导都会非常感激。

堆栈跟踪更新

moreButtonPressed

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

更新2

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

中加入fetchedResultsController
FavouritesTab

1 个答案:

答案 0 :(得分: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中执行提取时,数据将正确显示。