手动内存管理

当与 C API 接口时,可能想要退出 Swift 引用计数器。这样做是通过非托管对象实现的。

如果需要提供一个 C 型函数的类型惩罚指针,请使用 Unmanaged 结构的 toOpaque 方法获取原始指针,并使用 fromOpaque 恢复原始实例:

setupDisplayLink() {
  let pointerToSelf: UnsafeRawPointer = Unmanaged.passUnretained(self).toOpaque()
  CVDisplayLinkSetOutputCallback(self.displayLink, self.redraw, pointerToSelf)
}

func redraw(pointerToSelf: UnsafeRawPointer, /* args omitted */) {
  let recoveredSelf = Unmanaged<Self>.fromOpaque(pointerToSelf).takeUnretainedValue()
  recoveredSelf.doRedraw()
}

请注意,如果使用 passUnretained 和对应物,则必须采取与 unowned 参考相同的所有预防措施。

要与传统的 Objective-C API 进行交互,可能需要手动影响某个对象的引用计数。因为 Unmanaged 有各自的方法 retainrelease。尽管如此,更希望使用 passRetainedtakeRetainedValue,它们在返回结果之前执行保留:

func preferredFilenameExtension(for uti: String) -> String! {
  let result = UTTypeCopyPreferredTagWithClass(uti, kUTTagClassFilenameExtension)
  guard result != nil else { return nil }

  return result!.takeRetainedValue() as String
}

这些解决方案应始终是最后的选择,语言本地 API 始终是首选。