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

关于这个问题:Changing the UIImage of a specific UITableViewCell when an event occurs,我在LeafetsAndVideos中设置了“收藏”特定单元格的用法。通过使用Core Data,我将获取最喜欢的单元格的标题,并将其添加到Core Data模型中。之所以这样做,是因为第二个选项卡称为Favourites,并且通过使用NSFetchedResultsController,我在UITableView中填充了所有已“收藏”的单元格。

那个公园真的很好。

现在的问题是,当在LeafletsAndVideos UITableView中时,我喜欢一个单元格,并且通过在Favourites上使用NSFRC使其立即显示在FavouritesTableViewController选项卡中,但是如果我不喜欢同一单元格,则希望将其从中删除Favourites标签。

问题

问题是,当我不喜欢某个单元格时,它会再次添加到Favourites选项卡中。

为了清楚起见,当我说“收藏夹”时,假设我点击了该单元格(didSelectCell),因此当我再次点击该单元格时,它不再显示。
LeafletsAndTable UITableView没有引用NSFRC,它实际上并不需要引用,因为单元格是由Languages NSMutableArray's中设置的UITableView填充的(我完全理解我可以只将Core Data用作标题,但这在此方面很复杂设置-Core Data仅用作检测Favourited单元格标题的机制。

在我的LeafletAndVideo UITableView中,设置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上调用fetch。
- (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

fetchedResultsController中包括FavouritesTab
- (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;
}

最佳答案

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

您必须像这样的代码一样在LeafletsAndVideos控制器中执行所有与Core Data相关的任务

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执行提取时,数据将正确显示。

10-08 12:10