我在保存核心数据中的数据方面存在问题。我必须点击按钮在数据库中保存多个图书信息。当我点击按钮时,我调用该方法并将书籍信息保存在数据库中。对于前三次点击,可以保存书籍信息并且ui也是响应式的。当我第四次点击按钮时,ui会在保存结束时冻结。
代码如下。
+(void) storeBookInfo:(NSDictionary *) bookInfo inContext:(NSManagedObjectContext *) ctx {
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSManagedObjectContext *tempCtx = [[NSManagedObjectContext alloc]initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[tempCtx setPersistentStoreCoordinator:appDelegate.persistentStoreCoordinator];
[tempCtx setUndoManager:nil];
NSNotificationCenter *notify = [NSNotificationCenter defaultCenter];
[notify addObserver:self
selector:@selector(mergeChanges:)
name:NSManagedObjectContextDidSaveNotification
object:tempCtx];
NSFetchRequest *req = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Book" inManagedObjectContext:tempCtx];
[req setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"bid==%@", [bookInfo objectForKey:@"bid"]];
[req setPredicate:predicate];
[req setFetchLimit:1];
[req setReturnsObjectsAsFaults:NO];
NSArray *bookObjects = [tempCtx executeFetchRequest:req error:nil];
if([bookObjects count] > 0){
NSError *err;
Book *wi = [bookObjects objectAtIndex:0];
wi.purchaseInfo = [NSNumber numberWithInt:[[bookInfo objectForKey:@"purchaseInfo"] intValue]];
if (![tempCtx save:&err]) {
NSLog(@"Problem saving book info..");
NSLog(@"err: %@", [err userInfo]);
[[NSNotificationCenter defaultCenter] removeObserver:self];
[tempCtx undo];
tempCtx = nil;
} else {
NSLog(@"Book saved. in if part");
tempCtx = nil;
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
}
else {
Book *book = [NSEntityDescription insertNewObjectForEntityForName:@"Book" inManagedObjectContext:tempCtx];
book.bid = [bookInfo objectForKey:@"bid"];
book.title = [bookInfo objectForKey:@"title"];
book.thumbnailImgId = [bookInfo objectForKey:@"imageUrl"];
book.downloadState = [NSNumber numberWithInt:0];
book.pid = [bookInfo objectForKey:@"pid"];
book.purchaseInfo = [NSNumber numberWithInt:[[bookInfo objectForKey:@"purchaseInfo"] intValue]];
book.discription = [bookInfo objectForKey:@"desc"];
NSError *err;
if (![tempCtx save:&err]) {
NSLog(@"Problem saving book ifo..");
NSLog(@"err: %@", [err userInfo]);
[[NSNotificationCenter defaultCenter] removeObserver:self];
[tempCtx undo];
tempCtx = nil;
} else {
NSLog(@"Book saved.");
tempCtx = nil;
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
}
}
+ (void)mergeChanges:(NSNotification*)notification
{
AppDelegate *theDelegate = [[UIApplication sharedApplication] delegate];
[[theDelegate managedObjectContext] performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification:) withObject:notification waitUntilDone:YES];
}
我已经创建了一个临时MOC,因为代码在后台线程中,每次保存后我都会发送通知。
第四次点击按钮app冻结。我被困在这一点上。
答案 0 :(得分:0)
*假设:
+storeBookInfo:inContext:
总是在BG线程中调用
使用ARC
*请注意:
self
中的+storeBookInfo:inContext:
是类本身,removeObserver:
上会删除所有观察信息(您可能会错过某些时间的合并,请考虑使用removeObserver:name:object:
代替,而不是立即取消tempCtx)
您正在使用:NSPrivateQueueConcurrencyType
但未使用performBlock:
或performBlockAndWait:
方法(请考虑使用NSConfinementConcurrencyType
)
如果在主线程上调用+mergeChanges:
,您的应用程序将被卡住
(考虑添加:
NSAssert(![NSThread isMainThread],@"The application will get stuck");
确保或修改合并流程 )