3

我正在尝试获取与视图关联的图像,但 Xcode 返回错误。这是代码:

@IBOutlet var imageView: IKImageView // Link to the image view.

func saveImage() {
    var newImage: CGImageRef = imageView.image() // Line with an error.
}

我有一个awakeFromNib在视图中设置图像的功能。上面的代码返回 me 'Unmanaged<CGImage>' is not convertible to 'CGImageRef'

我知道类型在 Swift 中是可选的,但我不明白为什么会出现此错误,IKImageView 类参考明确表示获取 IKImageView 的图像返回 CGImageRef。

4

2 回答 2

6

这与将 Objective C API 桥接到 Swift 有关。API 的 Swift 版本已经通过将原始的 Objective C 标头转换为 Swift 版本来桥接(我相信大部分是自动的)。在许多情况下,转换可以计算出你将要返回什么样的值,因此在 Swift 中你会得到一个“正常”的类型,你可以按照你的期望使用它。

但是,转换仍在进行中。在这种情况下,您看到的是一种用于帮助您在转换过程不知道您是否要取回为您保留的对象时手动管理内存的类型,因为 API 不没有它可以用来弄清楚的常规注释。

Unmanaged类型有效地表示“您必须告诉我如何处理包含的值才能获得正确的内存管理”。一旦你得到一个非托管值,你应该调用它的两个方法之一:

takeUnretainedValue() 
takeRetainedValue()

...取决于您返回的对象是“+0”还是“+1”。因此,您应该执行以下操作:

var newImage: CGImage = imageView.image().takeUnretainedValue()

一旦你这样做了(你应该立即这样做),你已经给了 Swift 足够的提示,它现在可以使用 ARC 正确地管理对象,并为你自己获得了正确类型的有效引用.

在今年的“Swift Interoperability in Depth”WWDC 视频的结尾处简要介绍了这一点。

于 2014-06-19T20:00:37.493 回答
1

查看新版本参考中显示 Swift 声明image()的方法,您会看到它返回一个. 这意味着 ImageKit 没有设置为编译器可以在其 API 上自动推断 CoreFoundation 内存管理语义。(这会影响 Swift 翻译和 ObjC 隐式 ARC 桥接。)它应该,所以这将是一个很好的错误来归档.IKImageViewUnmanaged<CGImage>!

当编译器无法自动推断它们的 ARC 行为时, Swift 类型Unmanaged<T>是您与 CF 类型交互的方式。要获取底层类型,请调用takeUnretainedValue()takeRetainedValue()- 您必须根据您调用的 API 是否已知已经保留了它返回的值来选择哪个。令人兴奋的猜测!(同样,消除猜测将是一个很好的归档错误。)您可以在Using Swift with Cocoa and Objective-C中阅读更多相关信息。

无论如何,在这种情况下,您可能会期望提供它时IKImageView不会增加保留计数CGImage,因此您可以Unmanaged像这样展开:

var newImage: CGImage = imageView.image().takeUnretainedValue()

另请注意,在 Swift 中使用 CF 类型时不需要Ref后缀。(CGImageRef是 . 的类型别名CGImage。) Swift 让您可以将 CF 类型视为 Swift 对象(而不是作为指向不透明 C 类型的 C 指针)。

于 2014-06-19T20:10:46.250 回答