在 Swift 中同步异步内容

Posted

技术标签:

【中文标题】在 Swift 中同步异步内容【英文标题】:Synchronizing Async Stuff in Swift 【发布时间】:2015-06-15 18:36:40 【问题描述】:

我不确定为什么 Apple 会分块设计这么多东西…… 由于提供的选项,至少“@​​987654321@”中的问题能够得到解决。但是,我需要的其他一些东西不是选项提供的。

例如:

func getAssetUrl(asset: PHAsset) -> NSURL 
    var option = PHContentEditingInputRequestOptions()
    asset.requestContentEditingInputWithOptions(option, completionHandler: (contentEditingInput, info) -> Void in
            var imageURL = contentEditingInput.fullSizeImageURL
        println(imageURL)
        )
    return NSURL()

在这些情况下,我只想要带块的函数(例如 requestContentEditingInputWithOptions 同步执行,以便我可以返回 imageURL)。有没有办法做到这一点? (我尝试过使用一些 dispatch 命令,但还没有成功)。

请注意,我需要返回 imageURL。不要试图给我一个解决方案,让我在块内写东西并且不返回 imageURL。

【问题讨论】:

为什么需要返回图片URL?为什么不能使用遵循完善的异步模式(例如添加一个completion 闭包,当你有 URL 时调用它)?是的,您可以使用信号量使异步方法同步运行,但这通常是一个可怕的想法。他们使这种方法是异步的是有原因的。遵循异步模式和使用 completion 闭包非常容易。那为什么不这样做呢?!? 我需要将 URL 传递给一个预先存在的函数,该函数只接受一个 URL。我想我可以使用您在下面编写的 completionHandler,但我不确定未来的函数是否会采用 URL 和其他参数。如果可能的话,你能展示如何使用信号量吗?我无法正确执行此操作。 只需将接受 URL 参数的函数放在闭包内部调用即可。这是处理这个问题的正确方法。如果您在错误的时间执行此操作,则使此行为同步可能会导致糟糕的用户体验并让看门狗进程杀死您的应用程序。 还是一头雾水。假设我有以下函数: A. printNSUrlAsString(NSUrl) B. relocateNSUrlToLocation(NSUrl, destination) C. getFile(NSUrl) 如果我将以下所有内容放在闭包中,那么当我只想获取文件时我可能正在重新定位?另外我不确定为什么需要异步处理获取文件的 URL...也许我没有使用正确的方法来获取 URL? 照片是异步的,因为你不能假设资源是本地的。不管是什么原因,我们总是可以确信异步不仅仅是因为困难,而是因为一个很好的理由。我们在所有地方都使用异步模式,因此您不妨对它们感到满意。回到您的示例,如果 relo 是异步方法,那么您将让它使用 completionHandler 闭包模式本身,然后嵌套它们。如果你有具体的例子让你觉得异步模式很难,编辑你的问题给我们一个真实的场景,我们可以告诉你如何解决它。 【参考方案1】:

我知道你明确要求不要看到这个答案,但为了未来的读者,我觉得有必要发布处理异步方法的正确方法,即自己遵循异步模式并使用completionHandler

func getAssetUrl(asset: PHAsset, completionHandler: @escaping (URL?) -> Void) 
    let option = PHContentEditingInputRequestOptions()
    asset.requestContentEditingInput(with: option)  contentEditingInput, _ in
        completionHandler(contentEditingInput?.fullSizeImageURL)
    

你会这样使用它:

getAssetUrl(asset)  url in
    guard let url = url else  return 

    // do something with URL here


// anything that was here that needs URL now goes above, inside the `completionHandler` closure

还有其他更复杂的模式(操作、第三方承诺/期货实现等),但completionHandler 模式通常可以非常优雅地处理这些情况。

【讨论】:

阅读 OP 中的评论。我不确定如何优雅地使用 completionHandlers 来保证未来的功能能够正常工作。

以上是关于在 Swift 中同步异步内容的主要内容,如果未能解决你的问题,请参考以下文章

Swift3.0:Get/Post同步和异步请求

同步 API 请求到异步 API 请求 Swift 2.2

iOS中的同步与异步队列

swift/OC中的死锁问题

Async 异步转同步详细流程解释

1. 同步异步阻塞非阻塞