【发布时间】:2015-07-16 11:22:36
【问题描述】:
我面临一个奇怪的问题“未能及时更新场景”。下载数据后,我将其存储到核心数据中。如果应用程序在前台,一切都会正常工作。仅当我在将数据存储到 Core Data 的过程中连续在状态、后台和前台之间切换应用程序时,我才会遇到此崩溃。在调试模式下不会发生这种崩溃。
我尝试将日志放在Core Data操作方法的不同阶段,我发现了应用程序实际崩溃的点。在 UI 中,我使用以下代码
DatabaseManagerClass *database = [[DatabaseManagerClass alloc]init];
[database deleteDataFromFormTable:nil];
[database insertDataInChecklistTable:[self.responseDictionary valueForKey:@"checklists"]];
[self performSelectorOnMainThread:@selector(mainThreadTask) withObject:nil waitUntilDone:YES];`
崩溃发生在方法“insertDataInChecklistTable”中。我检查了 insertDataInChecklistTable 工作的线程。它仅在主线程中。任何人都可以提出一些建议来解决这个问题。
提前致谢, 斯里。
带有执行块的更新代码
-(void)insertDataInFormColumnsTable:(NSMutableArray*)responseArray withForm:(Form*)form
{ AppDelegate objAppDelegate = (AppDelegate)[[UIApplication sharedApplication] delegate];
NSManagedObjectContext *moc = [objAppDelegate managedObjectContext];
NSManagedObjectContext *bgMOC = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[bgMOC performBlock:^{
for (int count=0; count<[responseArray count]; count++)
{
NSDictionary *columnDict = [responseArray objectAtIndex:count];
Form_Column *formColumn = [NSEntityDescription insertNewObjectForEntityForName:@"Form_Column" inManagedObjectContext:moc];
if ([columnDict valueForKey:FORMULA]!=[NSNull null]) //Added by mritunjay
formColumn.formula = [columnDict valueForKey:FORMULA];
else
formColumn.formula=nil;
if ([columnDict valueForKey:ASP_EDITABLE]!=[NSNull null])
formColumn.asp_editable = [columnDict valueForKey:ASP_EDITABLE];
else
formColumn.asp_editable=nil;
if ([columnDict valueForKey:CM_EDITABLE]!=[NSNull null])
formColumn.cm_editable = [columnDict valueForKey:CM_EDITABLE];
else
formColumn.cm_editable=nil;
if ([columnDict valueForKey:IM_EDITABLE]!=[NSNull null])
formColumn.im_editable = [columnDict valueForKey:IM_EDITABLE];
else
formColumn.im_editable=nil;
if ([columnDict valueForKey:SP_EDITABLE]!=[NSNull null])
formColumn.sp_editable = [columnDict valueForKey:SP_EDITABLE];
else
formColumn.sp_editable=nil;
if ([columnDict valueForKey:ASP_EDITABLE]!=[NSNull null])
formColumn.dialog_row = [columnDict valueForKey:ASP_EDITABLE];
else
formColumn.dialog_row=nil;
if ([columnDict valueForKey:INDEX]!=[NSNull null])
formColumn.index = [columnDict valueForKey:INDEX];
else
formColumn.index=nil;
if ([columnDict valueForKey:WEB_ONLY]!=[NSNull null])
formColumn.web_only = [columnDict valueForKey:WEB_ONLY];
else
formColumn.web_only=nil;
if ([columnDict valueForKey:LABEL]!=[NSNull null])
formColumn.label = [columnDict valueForKey:LABEL];
else
formColumn.label=nil;
formColumn.form_id = form.form_id;
if ([columnDict valueForKey:ID]!=[NSNull null])
formColumn.column_id=[columnDict valueForKey:ID];
else
formColumn.column_id=nil;
if ([columnDict valueForKey:TYPE]!=[NSNull null])
formColumn.type=[columnDict valueForKey:TYPE];
else
formColumn.type=nil;
NSArray *selectionArray = [columnDict valueForKey:SELECTIONS];
if ([selectionArray count]) {
for (int count = 0; count < [selectionArray count]; count++)
{
Form_Sub_Columns *formSubColumns = [NSEntityDescription insertNewObjectForEntityForName:@"Form_Sub_Columns" inManagedObjectContext:moc];
NSDictionary *subColumnDict = [selectionArray objectAtIndex:count];
if ([subColumnDict valueForKey:ID]!=[NSNull null])
formSubColumns.column_id=[subColumnDict valueForKey:ID];
else
formSubColumns.column_id=nil;
if ([subColumnDict valueForKey:LABEL]!=[NSNull null])
formSubColumns.label=[subColumnDict valueForKey:LABEL];
else
formSubColumns.label=nil;
if ([subColumnDict valueForKey:REQUIRES_REMARKS]!=[NSNull null])
formSubColumns.requires_remarks=[subColumnDict valueForKey:REQUIRES_REMARKS];
else
formSubColumns.requires_remarks=nil;
if ([subColumnDict valueForKey:VALUE]!=[NSNull null])
formSubColumns.value=[subColumnDict valueForKey:VALUE];
else
formSubColumns.value=nil;
if ([subColumnDict valueForKey:DESCRIPTION]!=[NSNull null])
formSubColumns.description_name=[subColumnDict valueForKey:DESCRIPTION];
else
formSubColumns.description_name=nil;
if ([subColumnDict valueForKey:SELECTION_TYPE_ID]!=[NSNull null])
formSubColumns.selection_type_id=[subColumnDict valueForKey:SELECTION_TYPE_ID];
else
formSubColumns.value=nil;
[formColumn addSun_columnsObject:formSubColumns];
}
}
[formColumn addFormObject:form];
[form addColumnsObject:formColumn];
}
if([form.enable_attachment boolValue])
{
Form_Column *formColumn = [NSEntityDescription insertNewObjectForEntityForName:@"Form_Column" inManagedObjectContext:moc];
formColumn.label = @"Add Attachments";
formColumn.form_id = form.form_id;
formColumn.index = [NSNumber numberWithInt:998];
formColumn.column_id=[NSNumber numberWithInt:998]; // hardcoded if Attachment is Enabled.
formColumn.web_only = [NSNumber numberWithInt:0];
formColumn.type=[NSNumber numberWithInt:-1];
[form addColumnsObject:formColumn];
}
if ([[NSThread currentThread] isMainThread]) {
NSLog(@"Main Thread inside block");
}
else {
NSLog(@"Not main thread inside block");
}
NSError *error;
if(![bgMOC save:&error]){
NSLog(@"Error %@", [error localizedDescription]);
}
}];
}
【问题讨论】:
-
如果你把实际的堆栈跟踪放在你的问题中会很有帮助,这样我们就可以看到什么时候被调用了。我还建议 NOT 使用
-performSelectorOnMainThread:,因为它隐藏了它之前的堆栈跟踪(它基本上被包裹在一个 try/catch 中)。dispatch_async是将某些东西放到主线程上的更好解决方案。但总的来说,如果您将数据写入 Core Data 它不应该在主线程上。您阻塞主线程很可能导致此崩溃。 -
马库斯,感谢您回复我。我理解您所说的 performSelectorOnMainThread:调用选择器方法时不会发生实际崩溃。选择器方法调用前的行,执行数据库操作的方法。崩溃是在这种方法中发生的。所以我不应该在主线程中调用数据库操作。最后,我将日志放入 db 操作方法中,发现实际崩溃发生在 Coredata 的 addObject 方法中。真的很难找到解决方案。
-
您的崩溃正在发生,因为您阻塞主线程的时间过长并且操作系统正在杀死您的应用程序。在
-insertDataInChecklistTable上放一个断点,看看你在哪个线程上。你在主线吗?如果没有,请发布该方法的代码。 -
Marcus,InsertDataInChecklistTable 方法正在 MainThread 中调用。
标签: ios objective-c multithreading core-data