我目前正在为 CGImage
的 copy
方法(或者 CGImage
的一般工作方式?)苦苦挣扎。
背景:我用 UnsafeMutablePointer
操作了一张图片,结果出现了 EXC_BAD_ACCESS 错误。我发现,这是由 CGImage
已经显示在 UIView
中(封装在 UIImage
中)引起的。所以我创建了 CGImage
的副本并且它可以工作。由此我得出结论,copy
必须创建图像的真实副本。
但是:在用下面的代码检查指针时,我注意到两个指针指向的地址是相同的。
这怎么可能?
import UIKit
var uiImageIn = UIImage(named: "image2.png")!
var image1 = uiImageIn.cgImage!
var image2 = image1.copy()!
var ptr1 = UnsafeMutablePointer<UInt8>.init(mutating: CFDataGetBytePtr(image1.dataProvider!.data)!)
var ptr2 = UnsafeMutablePointer<UInt8>.init(mutating: CFDataGetBytePtr(image2.dataProvider!.data)!)
print("Image1Ptr: \(ptr1)")
print("Image2Ptr: \(ptr2) --> Same result as for ptr1!?")
我希望 ptr1 和 ptr2 在这里有所不同。
更新
好的,找出我的错误:
根本没有必要创建 CGImage
的副本,因为访问 dataProvider
已经创建了位图数据的副本。但是:在我上面的代码中,我没有将 dataProvider
分配给任何变量。因此,它会立即被释放,并且大部分时间都会重复使用该地址(此外,如果我通过其中一个指针访问数据,因为 dataProvider
已经被释放,它会导致错误)。
在下面的例子中,指针的地址是不同的: 导入 UIKit
var uiImageIn = UIImage(named: "image.png")!
var image1 = uiImageIn.cgImage!
var data1 = image1.dataProvider!.data
var data2 = image1.dataProvider!.data
var ptr1 = UnsafeMutablePointer<UInt8>.init(mutating: CFDataGetBytePtr(data1)!)
var ptr2 = UnsafeMutablePointer<UInt8>.init(mutating: CFDataGetBytePtr(data2)!)
print("Image1Ptr: \(ptr1)")
print("Image2Ptr: \(ptr2)")
最佳答案
你的期望是错误的。 copy()
创建浅拷贝。这意味着创建了一个新对象,但所有内部结构仅通过引用进行复制。这意味着即使您收到一个新的 CGImage
,数据提供者仍将是相同的对象(和指针)。
另请注意,对于不可变对象(immutable对象),copy
函数不必返回新对象。它可以只返回前一个对象(例如 NSArray
会发生什么)。
在随机 CGImage
的提供者内部修改 data
可能不是一件好事,因为你不知道数据的内部结构(是 JPEG数据源?是PNG数据源?是位图?)
关于ios - 为什么 CGImage 的 copy() 方法会在相同的内存地址上生成图像?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53932107/