【问题标题】:Why app is blocked by semaphore?为什么应用程序被信号量阻止?
【发布时间】:2016-08-22 10:42:51
【问题描述】:

我有以下函数假设返回 [CIImage] 用于我的目的 - 在 tableView 中显示照片的一些元数据。

func getCIImages() -> [CIImage] {
    var images = [CIImage]()
    let assets = PHAsset.fetchAssetsWithMediaType(.Image, options: nil)

    for i in 0..<assets.count {
        guard let asset = assets[i] as? PHAsset else {fatalError("Cannot cast as PHAsset")}  
        let semaphore = dispatch_semaphore_create(0)

        asset.requestContentEditingInputWithOptions(nil) { contentEditingInput, _ in
            //Get full image
            guard let url = contentEditingInput?.fullSizeImageURL else {return}
            guard let inputImage = CIImage(contentsOfURL: url) else {return}
            images.append(inputImage)
            dispatch_semaphore_signal(semaphore)
        }
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)
    }
    return images
}

但它停留在信号量等待中并且没有更进一步。我浏览了许多教程,但 GCD 的其他变体不起作用。我认为这是因为模拟器,我不知道,无法在真实设备上测试。请帮忙。

【问题讨论】:

  • 你为什么要强制一个准同步请求?
  • @vadian 因为我想在tableView 中显示CIImages 的一些元数据,并且可以通过一个tableView.reloadData() 调用以同步方式完成。

标签: ios swift grand-central-dispatch semaphore phasset


【解决方案1】:

requestContentEditingInputWithOptions 回调闭包内部的守卫可防止将信号发送到信号量。 在这种情况下(当您需要清理操作时)最好使用defer。在你的情况下:

asset.requestContentEditingInputWithOptions(nil) { contentEditingInput, _ in
    defer { dispatch_semaphore_signal(semaphore) }

    //Get full image
    guard let url = contentEditingInput?.fullSizeImageURL else {return}
    guard let inputImage = CIImage(contentsOfURL: url) else {return}
    images.append(inputImage)
}

更新

除了清理错误还有另一个。在主线程上调用 requestContentEditingInputWithOptions 的完成关闭。这意味着如果你用信号量阻塞主线程:完成闭包也会被阻塞执行。要修复阻塞的信号量问题,您需要在与主线程不同的线程上调用 getCIImages

无论如何,使异步事物同步是错误的。你应该考虑不同的方法。

【讨论】:

  • 这就是为什么引入defer的原因!
  • 没有一个guard 不调用else 语句。此代码产生与我的代码相同的行为 - 程序冻结
  • @Silmaril 即使我异步调用我如何返回所有图像?
  • @AndreyM。这取决于您的要求。但我为您创建了一个简单的示例:gitlab.com/snippets/24749。希望这足以理解这个想法。
猜你喜欢
  • 1970-01-01
  • 2015-06-01
  • 2012-09-03
  • 2021-07-28
  • 1970-01-01
  • 1970-01-01
  • 2020-02-29
  • 2011-04-03
  • 2016-06-19
相关资源
最近更新 更多