gpt4 book ai didi

ios - 使用 +[NSThread sleep :] to resolve a deadlock issue

转载 作者:可可西里 更新时间:2023-11-01 06:11:21 24 4
gpt4 key购买 nike

我刚刚“解决”了似乎是死锁或同步的问题:

    [NSThread sleepForTimeInterval:0.1];

在将 IPOD 库中的 MPMediaItem(音乐/图像)属性引用附加到对象实例的应用程序中,这些对象通过 CoreData 回存。我在这里的兴趣是准确了解正在发生的事情以及这种情况下的最佳做法是什么。开始了:

每次复制的方法如下:

  1. 用户创建了一个新项目。

    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);
    }
    }];
  2. 稍后 managedObjectContext 用于关联对象实例并混合 CoreData 模型

    TheProject *theProject = [TheProject projectWithInfo:theProjectInfo
    inManagedObjectContext:doc.managedObjectContext];
  3. 用户稍后创建“CustomAction”对象,向其添加“ChElement”并将“MusicElement”与 ChElement 相关联。 (这些是 CoreData 模型对象的化名)。 MusicElement 是通过 IPOD 库添加的。

    #define PLAYER [MPMusicPlayerController iPodMusicPlayer]
  4. 用户保存此项目,然后切换到一个现有项目,该项目已经创建了一个 CustomAction 对象,其中包含一个 ChElement 和一个 MusicElement。

  5. 用户从 tableView 中选择 ChElement 并导航到 detailView。当离开 ChElementTVC(类似于 Apple 文档中的 CoreData TableViewController 类的子类)时,这是必需的:

    - (void)viewWillDisappear:(BOOL)animated
    {
    [super viewWillDisappear:animated];
    self.fetchedResultsController.delegate = nil;
    }
  6. 在详细 View 中,用户更改 ChElement 对象的属性并保存项目。 detailView 调用它的委托(delegate) (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];
    }];
    }
  7. 由于委托(delegate) (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, r5, r6, r7, lr}
0x3586056a: add r7, sp, #12

(lldb) 反汇编-f

    CoreData _perform:
0x358604c4: push {r4, r5, r7, lr}

... snipped ...

0x35860560: blx 0x35938bf4 ; symbol stub for: dispatch_sync_f

-> 0x35860564: add sp, #12
0x35860566: pop {r4, r5, r7, pc}

另一种解决方法是可能的。在 -[ChElementTVC viewDidAppear:] 中对 fetchedResultsController.delegate 恢复进行编码也有效地延迟了主队列上的此设置。

另一种解决方法是在项目保存完成后在完成 block 中执行导航弹出:

    #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);

我认为保存操作在后台与主队列上的委托(delegate)恢复同时运行,但我不知道如何检验/证明/反驳该理论。

那么,有人可以解释发生了什么以及在这种情况下的最佳做法是什么吗?此外,欢迎提供学习引用。

最佳答案

我最终实现了第三种方法,即用完成 block 保存文档以序列化与 CoreData 存储交互的事务。​​

关于ios - 使用 +[NSThread sleep :] to resolve a deadlock issue,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12595421/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com