【问题标题】:How to open/create UIManagedDocument synchronously?如何同步打开/创建 UIManagedDocument?
【发布时间】:2012-05-06 01:12:57
【问题描述】:

如标题中所述,我想同步打开UIManagedDocument,即我希望我的执行等到打开完成。我只在 mainThread 上打开文档。

当前要打开的 API 使用块

[UIManagedDocument openWithCompletionHandler:(void (^)(BOOL success))];

link 中提到的锁使用在主线程以外的线程上运行良好。如果我在mainThread 上使用锁,它会冻结应用程序的执行。

任何建议都会有所帮助。谢谢。

【问题讨论】:

    标签: ios objective-c-blocks uimanageddocument


    【解决方案1】:

    首先,我要说我强烈反对这样做。您的主线程只是等待,在等待调用完成时什么也不做。在某些情况下,如果您的应用程序在主线程上没有响应,系统会终止您的应用程序。这是非常不寻常的。

    我想你应该是决定何时/如何使用各种编程工具的人。

    这正是你想要的......阻塞主线程直到完成处理程序运行。同样,我建议这样做,但嘿,这是一种工具,我会采取 NRA 的立场:枪支不会杀人......

    __block BOOL waitingOnCompletionHandler = YES;
    [object doSomethingWithCompletionHandler:^{
        // Do your work in the completion handler block and when done...
        waitingOnCompletionHandler = NO;
    }];
    while (waitingOnCompletionHandler) {
        usleep(USEC_PER_SEC/10);
    }
    

    另一个选项是执行运行循环。然而,这并不是真正同步的,因为运行循环实际上会处理其他事件。我在一些单元测试中使用了这种技术。它与上面类似,但仍然允许在主线程上发生其他事情(例如,完成处理程序可能会调用主队列上的操作,这可能不会在前面的方法中执行)。

    __block BOOL waitingOnCompletionHandler = YES;
    [object doSomethingWithCompletionHandler:^{
        // Do your work in the completion handler block and when done...
        waitingOnCompletionHandler = NO;
    }];
    while (waitingOnCompletionHandler) {
        NSDate *futureTime = [NSDate dateWithTimeIntervalSinceNow:0.1];
        [[NSRunLoop currentRunLoop] runUntilDate:futureTime];
    }
    

    还有其他方法,但这些方法简单易懂,并且像拇指酸痛一样突出,因此很容易知道您在做一些非正统的事情。

    我还应该指出,除了测试之外,我从未遇到过这样做的充分理由。您可以死锁您的代码,并且不从主运行循环返回是一个滑坡(即使您自己手动执行它 - 请注意,调用您的内容仍在等待并再次运行循环可能会重新输入该代码,或导致其他一些问题)。

    异步 ​​API 非常棒。条件变量方法或对并发队列使用屏障是在使用其他线程时进行同步的合理方法。同步主线程与您应该做的相反。

    祝你好运...并确保您登记您的枪支,并始终携带您的隐藏武器许可证。这当然是狂野的西部。总有一个约翰卫斯理哈登在那里寻找枪战。

    【讨论】:

    • ...感谢您的宝贵时间。我试图搜索没有块的旧 API 打开文档。任何想法,这是如何实现的?
    • UIManagedDocument 是一个相对较新的接口,我认为它没有同步 API。在内部,它有两个 ManagedObjectContext 对象……一个在主线程上,一个使用私有调度队列。所有 IO 操作都发生在后台,因此类的性质决定了使用异步 API。在块之前,异步 API 使用委托或通知来让调用者知道操作何时完成。
    • 这不起作用,当我尝试下面的代码时:__block BOOL waitingOnCompletionHandler = YES; [_managedDocument openWithCompletionHandler:^(BOOL 成功) { if (success) { DLog(@"打开文档成功!"); self.managedObjectContext = _managedDocument.managedObjectContext;等待完成处理程序 = 否; } }]; while (waitingOnCompletionHandler) { usleep(USEC_PER_SEC/10);主线程永远卡在那里......
    • @zolibra - 您陷入僵局的原因是 completionHandler 在您的情况下实际上有工作要做,它需要主线程来完成。所以它被阻塞在你已经阻塞的主线程上等待。这就是强烈反对这样做的部分原因。
    猜你喜欢
    • 2012-05-25
    • 1970-01-01
    • 2012-09-27
    • 1970-01-01
    • 1970-01-01
    • 2013-05-19
    • 1970-01-01
    • 2013-04-15
    • 1970-01-01
    相关资源
    最近更新 更多