我有一个简单的应用程序,它是两个选项卡式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
执行提取时,数据将正确显示。