如何在Swift中将CGImage保存为Data?

8
这段代码进行了类型检查和编译,但之后崩溃了。我该如何将 CGImage 保存为 Data,以便稍后再次读取呢?
let cgi: CGImage? = ...        
var mData = Data()
let imageDest = CGImageDestinationCreateWithData(mData as! CFMutableData, 
                                                 kUTTypePNG, 1, nil)!
CGImageDestinationAddImage(imageDest, cgi!, nil)
CGImageDestinationFinalize(imageDest)

最后一行崩溃。控制台中的错误是:
2018-01-17 19:25:43.656664-0500 HelloPencil[2799:3101092] -[_NSZeroData 
  appendBytes:length:]: unrecognized selector sent to instance 0x1c80029c0
2018-01-17 19:25:43.658420-0500 HelloPencil[2799:3101092] *** Terminating app 
  due to uncaught exception 'NSInvalidArgumentException', reason: 
  '-[_NSZeroData appendBytes:length:]: unrecognized selector 
  sent to instance 0x1c80029c0'

那个从Data转换为CFMutableData的强制转换是Xcode推荐的,但也许是错误的。
1个回答

17
问题出在你创建可变数据的方式。`Data`不能直接转换为`NSMutableData`。
从`Data`到`CFMutableData`的唯一方法是,先将其强制转换为`NSData`,然后获取它的可变副本`NSMutableData`,最后再将其转换为`CFMutableData`。

`NSMutableData`和`CFMutableData`可以无缝桥接

但在这种情况下,考虑到没有要转换的数据,这样做没有任何意义。只需使用`CFDataCreateMutable(nil, 0)`初始化一个新的`CFMutableData`对象即可。
if let cgi = cgi, 
    let mutableData = CFDataCreateMutable(nil, 0),
    let destination = CGImageDestinationCreateWithData(mutableData, "public.png" as CFString, 1, nil) {
    CGImageDestinationAddImage(destination, cgi, nil)
    if CGImageDestinationFinalize(destination) {
        let data = mutableData as Data
        if let image = UIImage(data: data) {
            print(image.size)
        }
    } else {
        print("Error writing Image")
    }
}

编辑/更新:Xcode 11 • Swift 5.1

extension CGImage {
    var png: Data? {
        guard let mutableData = CFDataCreateMutable(nil, 0),
            let destination = CGImageDestinationCreateWithData(mutableData, "public.png" as CFString, 1, nil) else { return nil }
        CGImageDestinationAddImage(destination, self, nil)
        guard CGImageDestinationFinalize(destination) else { return nil }
        return mutableData as Data
    }
}

谢谢,问题解决了。我可能会报告一个关于类型转换的 bug。如果从 A 转换成 B 成功了,我认为不能因为 A 其实不是 B 而在后面出现问题。 - Rob N

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接