我有一个带有谓词的fetchedResultsController,其中“isOpen == YES”
当调用closeCurrentClockSet时,我将该属性设置为NO。因此,它不应再出现在我的 tableView 上。
出于某种原因,这没有发生。
有人可以帮我解决这个问题吗?
-(void)closeCurrentClockSet
{
NSPredicate * predicate = [NSPredicate predicateWithFormat:@"isOpen == YES"];
NSArray *fetchedObjects =
[self fetchRequestForEntity:@"ClockSet"
withPredicate:predicate
inManagedObjectContext:[myAppDelegate managedObjectContext]];
ClockSet *currentClockSet = (ClockSet *)fetchedObjects.lastObject;
[currentClockSet setIsOpen:[NSNumber numberWithBool:NO]];
}
--
我还有几个方法,使用完全相同的方法,通过调用自定义fetchRequestForEntity:withPredicate:inManagedObjectContext方法。
在这些方法中,当更改属性时,tableView 会正确更新!但是上面的这个(closeCurrentClockSet)没有!我不知道为什么。
--
我的 fetchedResultsController 实现来自 Apple 的文档。
另外,还有一个细节。如果我将我的应用程序发送到后台。关闭它并重新打开,tableView 显示应该更新了!
我已尽力在 stackOverflow 上关注之前的问题。没运气。我也 NSLogged 这一点。对象被正确获取。这是正确的。isOpen 属性正在正确更新为NO。但由于某种原因,我的 fetchedResultsController 没有更新 tableView。
我确实尝试了几个“锤子”解决方案,比如 reloadData 和调用 performFetch。但这没有用。或者使用它们会有意义......
编辑:从头开始,它确实有效,在我的 resultsController 上的 performFetch 之后立即调用 reloadData但使用 reloadData 正在敲定一个解决方案。另外,它会删除所有动画。我希望我的控制器自动更新我的 tableView。
有人可以帮我解决这个问题吗?
任何帮助是极大的赞赏!
谢谢,
努诺
编辑:
完整的实现。
fetchedResultsController 非常标准和直接。其他一切都来自 Apple 的文档
- (NSFetchedResultsController *)fetchedResultsController
{
if (_fetchedResultsController) {
return _fetchedResultsController;
}
NSManagedObjectContext * managedObjectContext = [myAppDelegate managedObjectContext];
NSEntityDescription *entity =
[NSEntityDescription entityForName:@"ClockPair"
inManagedObjectContext:managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:entity];
NSString *predicate = [NSString stringWithFormat: @"clockSet.isOpen == YES"];
[fetchRequest setPredicate: [NSPredicate predicateWithFormat:predicate]];
NSSortDescriptor *sortDescriptor1 =
[[NSSortDescriptor alloc] initWithKey:@"clockIn" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor1, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
[fetchRequest setFetchBatchSize:20];
NSFetchedResultsController *theFetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:managedObjectContext
sectionNameKeyPath:nil
cacheName:@"Root"];
_fetchedResultsController = theFetchedResultsController;
_fetchedResultsController.delegate = self;
return _fetchedResultsController;
}
--
Apple 文档中的样板代码:
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
// The fetch controller is about to start sending change notifications, so prepare the table view for updates.
[self.tableView beginUpdates];
}
- (void)controller:(NSFetchedResultsController *)controller
didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath
forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath
{
UITableView *tableView = self.tableView;
switch(type) {
case NSFetchedResultsChangeInsert:
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
withRowAnimation:UITableViewRowAnimationTop];
break;
case NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationLeft];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
withRowAnimation:UITableViewRowAnimationTop];
break;
}
}
- (void)controller:(NSFetchedResultsController *)controller
didChangeSection:(id )sectionInfo
atIndex:(NSUInteger)sectionIndex
forChangeType:(NSFetchedResultsChangeType)type
{
UITableView *tableView = self.tableView;
switch(type) {
case NSFetchedResultsChangeInsert:
[tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex]
withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex]
withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
// The fetch controller has sent all current change notifications, so tell the table view to process all updates.
[self.tableView endUpdates];
}
第一次更新:
跟踪[managedObjectContext hasChanges]确实返回 YES,这是应该的。但是 fetchedResultsController 不会更新 tableView
第二次更新
didChangeObject:atIndexPath:在这种特殊情况下不会被调用!我还有 2 种方法,使用完全相同的代码,它们只是碰巧是不同的实体。他们完美地工作。感谢@Leonardo 指出这一点
第三次更新此方法,遵循相同的规则。但确实有效。
- (void)clockOut
{
NSPredicate * predicate = [NSPredicate predicateWithFormat:@"isOpen == %@", [NSNumber numberWithBool:YES]];
NSArray * fetchedObjects =
[self fetchRequestForEntity:@"ClockPair"
withPredicate:predicate
inManagedObjectContext:[myAppDelegate managedObjectContext]];
ClockPair *aClockPair = (ClockPair *)fetchedObjects.lastObject;
aClockPair.clockOut = [NSDate date];
aClockPair.isOpen = [NSNumber numberWithBool:NO];
}
有人对我可能遗漏的内容有任何其他想法吗?
谢谢,
努诺