我有一个简单的基于UIManagedDocument的Core Data应用程序。我是iOS新手编程的新手,我几乎没有把它搞定,而且我被卡住了。我有人NSManagedObjects存储在Core Data中。当我第一次启动应用程序时,没有任何条目,但如果我向上滑动一个模态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,甚至将它延迟到核心数据文档报告它被打开之后。什么都行不通。任何帮助将不胜感激。
答案 0 :(得分:0)
从粗略看一下你的代码,我注意到你是异步创建你的上下文。这很好,但是当上下文准备就绪时,您需要通知表视图控制器并让它调用reloadData。
数据存储中的完成处理程序需要在表视图控制器上设置context属性。
答案 1 :(得分:0)
NSFetchedResultsController
并没有神奇地更新你的tableView。我发现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;
}
在这里,我将NSFetechedResultsControllerDelegate
设置为自我。并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];
}