Iphone 我的核心数据代码有问题吗
我有一位客户就我的应用程序中的一个错误与我联系,我认为这与我使用的核心数据有关。这目前只是一个理论,因为我自己还不能重新创造这个问题 问题似乎是,如果用户创建了一个新的实体对象,然后直接编辑实体对象,则该对象似乎无法正确保存,并且用户下次打开应用程序时,该对象不在那里 如果用户创建实体对象并在未编辑的情况下退出应用程序,则不会出现问题,如果用户在重新打开应用程序后编辑对象,也不会出现问题 我只收到过一份关于这种情况的报告,所讨论的设备是运行IOS4.0.2的iPhone3G。我不能在iPhone3GS、iPhone4或通过模拟器(都运行4.0.2)重新创建它 我不是核心数据专家,我想知道我使用框架的方式是否有问题。如果有人能查看我下面的代码并告诉我他们是否发现了任何潜在的问题,我将不胜感激 我已经介绍了与相关类中的核心数据交互的方法 AppDelegateIphone 我的核心数据代码有问题吗,iphone,core-data,Iphone,Core Data,我有一位客户就我的应用程序中的一个错误与我联系,我认为这与我使用的核心数据有关。这目前只是一个理论,因为我自己还不能重新创造这个问题 问题似乎是,如果用户创建了一个新的实体对象,然后直接编辑实体对象,则该对象似乎无法正确保存,并且用户下次打开应用程序时,该对象不在那里 如果用户创建实体对象并在未编辑的情况下退出应用程序,则不会出现问题,如果用户在重新打开应用程序后编辑对象,也不会出现问题 我只收到过一份关于这种情况的报告,所讨论的设备是运行IOS4.0.2的iPhone3G。我不能在iPhone
- (void)applicationDidEnterBackground:(UIApplication *)application {
NSError *error = nil;
if (managedObjectContext_ != nil) {
if ([managedObjectContext_ hasChanges] && ![managedObjectContext_ save:&error]) {
// log
}
}
}
- (void)applicationWillTerminate:(UIApplication *)application {
NSError *error = nil;
if (managedObjectContext_ != nil) {
if ([managedObjectContext_ hasChanges] && ![managedObjectContext_ save:&error]) {
// log
}
}
}
- (NSManagedObjectContext *)managedObjectContext {
if (managedObjectContext_ != nil) {
return managedObjectContext_;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
managedObjectContext_ = [[NSManagedObjectContext alloc] init];
[managedObjectContext_ setPersistentStoreCoordinator:coordinator];
}
return managedObjectContext_;
}
- (NSManagedObjectModel *)managedObjectModel {
if (managedObjectModel_ != nil) {
return managedObjectModel_;
}
managedObjectModel_ = [[NSManagedObjectModel mergedModelFromBundles:nil] retain];
return managedObjectModel_;
}
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
if (persistentStoreCoordinator_ != nil) {
return persistentStoreCoordinator_;
}
NSURL *storeURL = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"mydatabase.sqlite"]];
NSError *error = nil;
persistentStoreCoordinator_ = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
if (![persistentStoreCoordinator_ addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
NSLog(@"An error occurred adding the persistentStoreCoordinator. %@, %@", error, [error userInfo]);
// Display an alert message if an error occurs
}
return persistentStoreCoordinator_;
}
控制器1(使用通过图像选择器选择的图像创建实体对象)
首先,你真的不应该忽视这些错误。你可能会在那里抛出一个错误,却永远不会知道 代码本身并没有什么特别之处,但在保存过程中很容易出现错误,可能是未设置非可选参数,等等
处理异常并从中查看。如果实体仅在
saveAction:
方法中创建,则如果用户在手动选择保存之前退出应用程序,则可能不会首先创建实体 问题是,我只在应用程序终止或后台时保存托管对象上下文
在应用程序退出之前,我只有大约5秒钟的时间保存用户创建的所有图像块。如果有很多图像,那么它们可能不会全部及时保存,这就是为什么在应用程序重新启动时它们不会出现的原因
这主要影响到iphone3g,因为它是我支持的所有型号中速度最慢的
我已经更新了代码,以便在进行更改时保存托管上下文。这解决了此问题,但暴露了另一个问题:
感谢您查看代码。我确实用日志消息处理这些错误,我只是删除了它们,并用注释替换它们,以便在这里发布代码,使其尽可能简短。
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
UIImage* selectedImage = [info objectForKey:UIImagePickerControllerOriginalImage];
// Create an image object for the new image.
NSManagedObject *image = [NSEntityDescription insertNewObjectForEntityForName:@"Image" inManagedObjectContext:managedObjectContext];
// Set the image for the image managed object.
[image setValue:[selectedImage scaleAndCropImageToScreenSize] forKey:@"image"];
// Create a thumbnail version of the image.
UIImage *imageThumbnail = [selectedImage thumbnailImage:50.0F];
// Create a new note
Note *note = [NSEntityDescription insertNewObjectForEntityForName:@"Note" inManagedObjectContext:managedObjectContext];
NSDate *now = [[NSDate alloc] init];
note.createdDate = now;
note.lastModifiedDate = now;
[now release];
note.thumbnail = imageThumbnail;
note.image = image;
}
[self dismissModalViewControllerAnimated:YES];
[picker release];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NotePadViewController *notePadController = [[NotePadViewController alloc] initWithNibName:@"NotePadView" bundle:nil];
Note *note = [[self fetchedResultsController] objectAtIndexPath:indexPath];
notePadController.note = note;
notePadController.title = note.notes;
[self.navigationController pushViewController:notePadController animated:YES];
[notePadController release];
}
- (NSFetchedResultsController *)fetchedResultsController {
if (fetchedResultsController != nil) {
return fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Note" inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
[fetchRequest setFetchBatchSize:20];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"createdDate" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:@"Root"];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
[aFetchedResultsController release];
[fetchRequest release];
[sortDescriptor release];
[sortDescriptors release];
NSError *error = nil;
if (![fetchedResultsController performFetch:&error]) {
NSLog(@"An error occured retrieving fetched results. %@, %@", error, [error userInfo]);
// Display an alert message if an error occurs
}
return fetchedResultsController;
}
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
[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: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 reloadSections:[NSIndexSet indexSetWithIndex:newIndexPath.section] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (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)controllerDidChangeContent:(NSFetchedResultsController *)controller {
[self setControllerTitle];
[self.tableView endUpdates];
}
- (void)saveAction:(id)sender {
NSDate *now = [[NSDate alloc] init];
if (self.note != nil && textView.text.length == 0) {
self.note.notes = nil;
self.note.lastModifiedDate = now;
} else if (textView.text.length != 0) {
// Create a new note if one does not exist
if (self.note == nil) {
VisualNotesAppDelegate *appDelegate = (VisualNotesAppDelegate *)[[UIApplication sharedApplication] delegate];
NSManagedObjectContext *managedObjectContext = appDelegate.managedObjectContext;
Note *newNote = [NSEntityDescription insertNewObjectForEntityForName:@"Note" inManagedObjectContext:managedObjectContext];
self.note = newNote;
self.note.createdDate = now;
}
self.note.lastModifiedDate = now;
self.note.notes = textView.text;
self.title = [note title];
}
[now release];
[self.textView resignFirstResponder];
}