Iphone NSFetchedResultsController不';t在启动后更新UITableView
我有一个简单的基于UIManagedDocument的核心数据应用程序。我对iOS编程还不熟悉,但我几乎还没有起步,我被卡住了。我将人员NSManagedObject存储在核心数据中。当我第一次启动应用程序时,没有任何条目,但如果我滑动一个模态VC并将其关闭,它们会神奇地出现。我的设计松散地基于iTunes U/Sanford课程中的“Photomania”应用程序,但使用单例CoreDataStore对象来处理managedObjectContext。这是我的CoreDataStore的代码:Iphone NSFetchedResultsController不';t在启动后更新UITableView,iphone,ios,objective-c,uitableview,nsfetchedresultscontroller,Iphone,Ios,Objective C,Uitableview,Nsfetchedresultscontroller,我有一个简单的基于UIManagedDocument的核心数据应用程序。我对iOS编程还不熟悉,但我几乎还没有起步,我被卡住了。我将人员NSManagedObject存储在核心数据中。当我第一次启动应用程序时,没有任何条目,但如果我滑动一个模态VC并将其关闭,它们会神奇地出现。我的设计松散地基于iTunes U/Sanford课程中的“Photomania”应用程序,但使用单例CoreDataStore对象来处理managedObjectContext。这是我的CoreDataStore的代码:
+ (CoreDataStore *)sharedStore
{
static CoreDataStore *sharedStore = nil;
if (!sharedStore)
sharedStore = [[super allocWithZone:nil] init];
return sharedStore;
}
+ (instancetype)allocWithZone:(struct _NSZone *)zone
{
return [self sharedStore];
}
- (NSManagedObjectContext *)getContext
{
NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory
inDomains:NSUserDomainMask] lastObject];
url = [url URLByAppendingPathComponent:@"dbDocument"];
UIManagedDocument *document = [[UIManagedDocument alloc] initWithFileURL:url];
if (![[NSFileManager defaultManager] fileExistsAtPath:[url path]]) {
NSLog(@"No file exists...");
[document saveToURL:url forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) {
NSLog(@"Document saveForCreating completionHandler invoked. Success: %hhd", success);
if (success) {
self.managedObjectContext = document.managedObjectContext;
NSLog(@"Got context for created file!!");
}
}];
} else if (document.documentState == UIDocumentStateClosed) {
NSLog(@"Document state is closed. documentState == %u", document.documentState);
[document openWithCompletionHandler:^(BOOL success) {
NSLog(@"Document opening success: %hhd", success);
if (success) {
self.managedObjectContext = document.managedObjectContext;
NSLog(@"Got context for now-opened file!!");
}
}];
} else {
self.managedObjectContext = document.managedObjectContext;
NSLog(@"Got context for already-opened file!!");
}
return self.managedObjectContext;
}
下面是PeopleListViewController的代码:
- (void)setManagedObjectContext:(NSManagedObjectContext *)managedObjectContext
{
_managedObjectContext = managedObjectContext;
if (managedObjectContext) {
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Person"];
request.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"name"
ascending:YES
selector:@selector(localizedCaseInsensitiveCompare:)]];
request.predicate = nil; // all Persons
self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:nil];
} else {
self.fetchedResultsController = nil;
}
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if (!self.managedObjectContext)
[self setManagedObjectContext:[[CoreDataStore sharedStore] getContext]];
}
这是发射后立即产生的结果:
这是模态VC:
这是在解除模式VC(点击取消)后:
我曾尝试在managedObjectContext上使用performFetch,甚至将其延迟到核心数据文档报告它被打开之后。什么都不管用。任何帮助都将不胜感激。粗略地看一下您的代码,我注意到您正在异步创建上下文。这很好,但是当上下文准备好时,您需要通知表视图控制器并让它调用reloadData
数据存储中的完成处理程序需要在表视图控制器上设置上下文属性。
NSFetchedResultsController
不会神奇地更新您的表视图。我发现Photomania有点复杂,因为像CoreDataViewController这样的辅助类很少。因此,只能通过调用reloadData
方法或使用一对beginUpdates
-endUpdates
来重新加载tableVew。和NSFetchedResultsController
只能通过调用performFetch:
方法进行更新。
我通常使用NSManagedObjectContext
getter:
- (NSFetchedResultsController*)fetchedResultsController
{
if (!_fetchedResultsController)
{
NSFetchRequest* fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"some entity name"];
fetchRequest.predicate = [NSPredicate predicateWithFormat:@"some predicate"];
fetchRequest.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES]];
_fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.context sectionNameKeyPath:@"name" cacheName:nil];
_fetchedResultsController.delegate = self;
NSError* error;
[_fetchedResultsController performFetch:&error];
if (error)
{
NSLog(@"Fetch ERROR. %@", error);
}
}
return _fetchedResultsController;
}
在这里,我将nsfetechedresultscoontrollerdelegate
设置为self。和performFetch:
获取数据。我了解代表的方法:
- (void)controllerWillChangeContent:(NSFetchedResultsController*)controller
{
[self.tableView beginUpdates];
}
- (void)controller:(NSFetchedResultsController*)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type
{
switch(type)
{
case NSFetchedResultsChangeInsert:
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex]
withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex]
withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (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:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:
[self configureCell:[tableView cellForRowAtIndexPath:indexPath]
atIndexPath:indexPath];
break;
case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController*)controller
{
[self.tableView endUpdates];
}
-(void)controllerWillChangeContent:(NSFetchedResultsController*)控制器
{
[self.tableView开始更新];
}
-(void)控制器:(NSFetchedResultsController*)控制器didChangeSection:(id)sectionInfo
atIndex:(nsInteger)ChangeType:(NSFetchedResultsChangeType)类型的节索引
{
开关(类型)
{
案例NSFetchedResultsChangesInsert:
[self.tableView insertSections:[NSIndexSet IndexSetWithiIndex:sectionIndex]
withRowAnimation:UITableViewRowAnimationFade];
打破
案例NSFetchedResultsChangeDelete:
[self.tableView deleteSections:[NSIndexSet IndexSetWithiIndex:sectionIndex]
withRowAnimation:UITableViewRowAnimationFade];
打破
}
}
-(void)控制器:(NSFetchedResultsController*)控制器didChangeObject:(id)一个对象
atIndexPath:(NSIndexPath*)indexPath forChangeType:(NSFetchedResultsChangeType)类型
newindepath:(nsindepath*)newindepath
{
UITableView*tableView=self.tableView;
开关(类型)
{
案例NSFetchedResultsChangesInsert:
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
withRowAnimation:UITableViewRowAnimationFade];
打破
案例NSFetchedResultsChangeDelete:
[tableView DeleteRowsatindExpath:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
打破
案例NSFetchedResultsChangeUpdate:
[self-configureCell:[tableView cellForRowAtIndexPath:indexPath]
atIndexPath:indexath];
打破
案例NSFetchedResultsChangeMove:
[tableView DeleteRowsatindExpath:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
withRowAnimation:UITableViewRowAnimationFade];
打破
}
}
-(void)controllerDidChangeContent:(NSFetchedResultsController*)控制器
{
[self.tableView endUpdates];
}
我在视图的末尾添加了一个performFetch:
将出现
,但结果是相同的BeginUpdate
/EndUpdate
不起作用,因为它是应用程序启动时。尚未进行任何更新。@LouValencia,请尝试在fetchedResultsController
setter中使用performFetch:
。因此,您将在必要时执行蚀刻:
,例如,在行数部分:
中。如果您的存储将发生更改,NSFetchedResultsControllerDelegate
方法将更新您的TableView我将如何执行此操作。我肯定这是需要在完成处理程序中进行的操作,但我不确定该如何进行。这听起来可能是个问题。我做了一个测试,发现[fetchedObjects count]
最初是0,然后在取消模式VC后是5。