在 UIImageWriteToSavedPhotosAlbum 中使用 contextInfo、UnsafeRawPointer - Swift 3

Wom*_*ble 1 ios swift

我有一个UITableView. 当一个单元格被点击时,我的应用程序会生成一个相关的图像。图像生成是在后台线程上完成的,因为有些图像需要相当长的时间来渲染。渲染图像后,UIImageWriteToSavedPhotosAlbum在主线程上调用。

由于任何数量的UIImageWriteToSavedPhotosAlbum任务可能以任何顺序进行,我需要一种方法来跟踪每个任务。我希望indexPath将所选单元格的存储为contextInfo,将其传递给UIImageWriteToSavedPhotosAlbum.

image:didFinishSavingWithError:contextInfo:被调用时,我需要从 contextInfo 中获取 indexPath。

但是,绝大多数在线示例UIImageWriteToSavedPhotosAlbum通过 nil for contextInfo.

我已经阅读了官方文档、Swift 3 指针迁移指南、头文件、使用桥接和强制转换的 Objective-C 代码,以及许多关于UnsafeMutableRawPointer/主题的 SO 线程UnsafeRawPointer

最终结果:我被无数的选择弄糊涂了,不知道我是否遗漏了一些明显的东西,我是否应该load()在指针数据上执行,应该调用unsafeBitCast(),还是应该将山羊献给众神。

或者,重新评估我的职业生涯,成为一名木匠。

一季度。如何IndexPath以适合 contextInfo 的形式存储 的实例?

Q2。一旦image:didFinishSavingWithError:contextInfo被调用,我如何形成一个IndexPathout of contextInfo,以便获取我存储的数据?谢谢你。

Wom*_*ble 5

最后,幸运的是偶然发现了一个关于 SO 的正确答案:

Swift 2 - UnsafeMutablePointer<Void> 到对象

基于上述答案,解决方案如下。欢迎任何改进或建议。

为了便于使用和调试,我将数据包装在引用类型中:

class ImageWritingContext : NSObject
{
    var indexPath = IndexPath()
    // ...
}
Run Code Online (Sandbox Code Playgroud)

数据需要牢固地保存。在这种情况下,在数组属性中。

fileprivate var imageWritingContexts = [ImageWritingContext]()
Run Code Online (Sandbox Code Playgroud)

当需要绘制时,我们将数据粘贴在包装器中并将包装器添加到数组中。

let context = ImageWritingContext()
context.indexPath = indexPath
self.imageWritingContexts.insert(context, at: 0)
Run Code Online (Sandbox Code Playgroud)

现在是魔法。

let contextRawPointer = UnsafeMutableRawPointer(Unmanaged.passUnretained(self.imageWritingContexts[0]).toOpaque())
Run Code Online (Sandbox Code Playgroud)

我们到了吗,我们到了吗?

let completionTarget: AnyObject = self
let completionSelector = #selector(self.image(_:didFinishSavingWithError:contextInfo:))

UIImageWriteToSavedPhotosAlbum(image,
    completionTarget,
    completionSelector,
    contextRawPointer)
Run Code Online (Sandbox Code Playgroud)

回调:

func image(_ image: UIImage,
    didFinishSavingWithError error: Error?,
    contextInfo: UnsafeRawPointer)
{
    // Perform error checking here.

    // Extract the data. Pop some valium first.
    let context: ImageWritingContext = Unmanaged<ImageWritingContext>
        .fromOpaque(contextInfo)
        .takeUnretainedValue()
    let indexPath = context.indexPath

    // Do something with the data.

    // Remember to remove the context from self.imageWritingContexts!
}
Run Code Online (Sandbox Code Playgroud)