2

我正在将图像从磁盘读取到 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 指针?

4

2 回答 2

3

The reason you have this problem, and the reason that CGImageRetain() fixes it, is because the CGImage is not retained by the block. This is because CGImageRef is not an Objective-C object pointer type. Blocks only automatically retain captured variables when they are Objective-C object pointer types.

So an alternate solution is to simply let the block capture an "object pointer type" version of it (all Core Foundation objects can be treated as Cocoa Objective-C objects, and vice versa):

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
}];
于 2013-07-24T00:49:25.087 回答
2

uiimage是自动释放的。因此,最有可能的cgImage是,当 自动释放时, 正在UIImage被释放。

您可以尝试保留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
}];
于 2013-07-23T17:13:21.330 回答