[NSThread sleepForTimeInterval:0.1];
在一个应用程序中,将来自IPOD库的MPMediaItem(音乐/图像)属性引用附加到对象实例,并通过CoreData对这些对象进行反向存储.我的兴趣是要准确了解发生了什么,以及在这种情况下最佳做法是什么.开始:
每次复制此内容的方法如下:
>用户创建一个新项目.
doc = [[UIManagedDocument alloc] initWithFileURL:docURL]; if (![[NSFileManager defaultManager] fileExistsAtPath:[docURL path]]) { [doc saveToURL:docURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) { if (success) { completionBlock(doc); } else { DLog(@"Failed document creation: %@",doc.localizedName); } }];
>稍后,managedObjectContext用于关联对象实例并对CoreData模型进行水合
TheProject *theProject = [TheProject projectWithInfo:theProjectInfo inManagedObjectContext:doc.managedObjectContext];
>用户稍后创建“CustomAction”对象,向其添加“ChElement”并将“MusicElement”与ChElement相关联. (这些是CoreData模型对象的假名). MusicElement通过IPOD库添加.
#define PLAYER [MPMusicPlayerController iPodMusicPlayer]
>用户保存此项目,然后切换到已创建一个CustomAction对象的现有项目,其中包含ChElement和MusicElement.
>用户从tableView中选择该ChElement并导航到detailView.
当导航离开ChElementTVC(类似于Apple文档中的CoreData TableViewController类的子类)时,这是必需的:
- (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; self.fetchedResultsController.delegate = nil; }
>在详细信息视图中,用户更改ChElement对象的属性并保存项目. detailView调用其委托(ChElementTVC)来进行保存.保存是保存NSManagedObject的UIManagedDocument实例.
#define SAVEDOC(__DOC__) [ProjectDocumentHelper saveProjectDocument:__DOC__] // Delegate - (void)chAddElementDetailViewController:(ChDetailViewController *)sender didPressSaveButton:(NSString *)message { SAVEDOC(THE_CURRENT_PROJECT_DOCUMENT); [self.navigationController popViewControllerAnimated:YES]; } // Helper Class + (void)saveProjectDocument:(UIManagedDocument *)targetDocument { NSManagedObjectContext *moc = targetDocument.managedObjectContext; [moc performBlockAndWait:^{ DLog(@" Process Pending Changes before saving : %@,Context = %@",targetDocument.description,moc); [moc processPendingChanges]; [targetDocument saveToURL:targetDocument.fileURL forSaveOperation:UIDocumentSaveForOverwriting completionHandler:NULL]; }]; }
>由于委托(ChElementTVC)从导航堆栈弹出detailView,
调用其viewWillAppear,并恢复fetchedResultsController.delegate.
- (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; if (!self.fetchedResultsController.delegate) { DLog(@"Sleep Now %@",self); //http://mobiledevelopertips.com/core-services/sleep-pause-or-block-a-thread.html [NSThread sleepForTimeInterval:0.1]; DLog(@"Wake up %@",self); [self fetchedResultsControllerWithPredicate:_savedPredicate]; // App Hangs Here ... This is sending messages to CoreData objects. [self.tableView reloadData]; }
没有[NSThread sleepForTimeInterval:0.1];该应用程序挂起.当我通过Xcode发送SIGINT时,我得到调试器并显示以下内容:
(lldb)bt
* thread #1: tid = 0x1c03,0x30e06054 libsystem_kernel.dylib semaphore_wait_trap + 8,stop reason = signal SIGINT frame #0: 0x30e06054 libsystem_kernel.dylib semaphore_wait_trap + 8 frame #1: 0x32c614f4 libdispatch.dylib _dispatch_thread_semaphore_wait$VARIANT$mp + 12 frame #2: 0x32c5f6a4 libdispatch.dylib _dispatch_barrier_sync_f_slow + 92 frame #3: 0x32c5f61e libdispatch.dylib dispatch_barrier_sync_f$VARIANT$mp + 22 frame #4: 0x32c5f266 libdispatch.dylib dispatch_sync_f$VARIANT$mp + 18 frame #5: 0x35860564 CoreData _perform + 160
(lldb)帧选择5
frame #5: 0x35860564 CoreData _perform + 160 CoreData _perform + 160: -> 0x35860564: add sp,#12 0x35860566: pop {r4,r5,r7,pc} CoreData -[NSManagedObjectContext(_NestedContextSupport) executeRequest:withContext:error:]: 0x35860568: push {r4,r6,lr} 0x3586056a: add r7,sp,#12
(lldb)反汇编-f
CoreData _perform: 0x358604c4: push {r4,lr} ... snipped ... 0x35860560: blx 0x35938bf4 ; symbol stub for: dispatch_sync_f -> 0x35860564: add sp,pc}
另一种解决方法是可行的.在 – [ChElementTVC viewDidAppear:]中编码fetchedResultsController.delegate恢复也有效地延迟了主队列上的此设置.
另一种解决方法是在项目保存完成后在完成块中执行导航弹出:
#define SAVEDOCWITHCOMPLETION(__DOC__,__COMPLETION_BLOCK__)[ProjectDocumentHelper saveProjectDocument:__DOC__ completionHandler:__COMPLETION_BLOCK__] void (^completionBlock)(BOOL) = ^(BOOL success) { [self.navigationController popViewControllerAnimated:YES]; }; SAVEDOCWITHCOMPLETION(THE_CURRENT_PROJECT_DOCUMENT,completionBlock);
我认为保存操作在后台与主队列上的委托恢复同时运行,但我不知道如何检查/证明/反驳该理论.
那么,有人可以解释发生了什么,在这种情况下最好的做法是什么?此外,赞赏研究参考.