我正在将磁盘中的图像读取到UIImage中,并在另一个工作队列块中使用其CGImage进行媒体处理。
现在,如果我在主队列中定义CGImageRef,并在工作队列中使用CGImageRef,我将获得EXC_BAD_ACCESS。像这样:
UIImage *uiimage = [UIImage imageWithContentsOfFile:[aPhoto completeLargeThumbFilePath]];
CGImageRef cgImage = uiimage.CGImage;
dispatch_queue_t dispatchQueue = dispatch_queue_create("mediaInputQueue", NULL);
[writerInput requestMediaDataWhenReadyOnQueue:dispatchQueue usingBlock:^{
// ... unrelated stuff
CVPixelBufferRef buffer = (CVPixelBufferRef)[self pixelBufferFromCGImage:cgImage size:size];
// ... unrelated stuff
}];
如果我使用uiimage。CGImage直接在工作队列中,然后我没有得到异常。我认为这与ARC内存管理有关。UIImage是一个objective-c对象,CGImageRef是一个指向c结构的指针。在第一种情况下,UIImage是在我可以使用它的CGImage之前发布的。
我的问题是,如何在另一个调度队列中直接使用在主队列中定义的C指针?
出现此问题的原因,以及CGImageRetain()
修复此问题的理由,是因为块未保留CGImage
。这是因为CGImageRef
不是Objective-C对象指针类型。只有当捕获的变量是Objective-C对象指针类型时,块才会自动保留这些变量。
因此,另一种解决方案是简单地让块捕获它的"对象指针类型"版本(所有Core Foundation对象都可以被视为Cocoa Objective-C对象,反之亦然):
UIImage *uiimage = [UIImage imageWithContentsOfFile:[aPhoto completeLargeThumbFilePath]];
CGImageRef cgImage = uiimage.CGImage;
id cgImageAsObject = (__bridge id)cgImage;
dispatch_queue_t dispatchQueue = dispatch_queue_create("mediaInputQueue", NULL);
[writerInput requestMediaDataWhenReadyOnQueue:dispatchQueue usingBlock:^{
// ... unrelated stuff
CGImageRef cgImageAgain = (__bridge CGImageRef)cgImageAsObject;
CVPixelBufferRef buffer = (CVPixelBufferRef)[self pixelBufferFromCGImage:cgImageAgain size:size];
// ... unrelated stuff
}];
uiimage
是自动释放的。因此,最有可能的是,当UIImage
被自动释放时,cgImage
正在被释放。
您可以尝试保留cgImage
,然后在块中释放它。或者,您可以在块中使用uiimage
(将[uiimage self];
添加到块的末尾——看起来很傻,但有效)。
根本问题是所谓的内部指针问题。您正在获取指向对象内部某个对象的指针,但没有保持对该对象的强引用。当对象离开时,内部指针指向的任何对象都会被收割,您只剩下一个悬挂的指针。
我会选择这个:
UIImage *uiimage = [UIImage imageWithContentsOfFile:[aPhoto completeLargeThumbFilePath]];
dispatch_queue_t dispatchQueue = dispatch_queue_create("mediaInputQueue", NULL);
[writerInput requestMediaDataWhenReadyOnQueue:dispatchQueue usingBlock:^{
CGImageRef cgImage = uiimage.CGImage;
// ... unrelated stuff
CVPixelBufferRef buffer = (CVPixelBufferRef)[self pixelBufferFromCGImage:cgImage size:size];
// ... unrelated stuff
}];