Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios imageWithCGImage:GCD内存问题_Ios_Objective C_Memory_Core Graphics_Grand Central Dispatch - Fatal编程技术网

Ios imageWithCGImage:GCD内存问题

Ios imageWithCGImage:GCD内存问题,ios,objective-c,memory,core-graphics,grand-central-dispatch,Ios,Objective C,Memory,Core Graphics,Grand Central Dispatch,当我仅在主线程上执行以下操作时,iref会立即自动删除: -(void)loadImage:(ALAsset*)asset{ @autoreleasepool { ALAssetRepresentation* rep = [asset defaultRepresentation]; CGImageRef iref = [rep fullScreenImage]; UIImage* image = [UIImage imageWithCGIm

当我仅在主线程上执行以下操作时,
iref
会立即自动删除:

-(void)loadImage:(ALAsset*)asset{
    @autoreleasepool {
        ALAssetRepresentation* rep = [asset defaultRepresentation];
        CGImageRef iref = [rep fullScreenImage];
        UIImage* image = [UIImage imageWithCGImage:iref
                                             scale:[rep scale]
                                       orientation:UIImageOrientationUp];

        [self.imageView setImage:image];
    }
}
但是当我在后台线程上执行imageWithCGImage:WithGCD时,
iref
不会像第一个示例中那样立即释放。大约一分钟后:

-(void)loadImage:(ALAsset*)asset{

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
        @autoreleasepool {
            ALAssetRepresentation* rep = [asset defaultRepresentation];
            CGImageRef iref = [rep fullScreenImage];
            UIImage* image = [UIImage imageWithCGImage:iref
                                                 scale:[rep scale]
                                           orientation:UIImageOrientationUp];

            dispatch_async(dispatch_get_main_queue(), ^(void) {
                [self.imageView setImage:image];
            });
        }
    });
}
如何使
CGImageRef
对象立即释放

先前的研究:

  • 当我用它记录时,泄漏仪器没有显示任何泄漏
  • 分配工具显示一个
    CGImageRef
    对象被分配,并且在它应该被释放后仍然存在大约一分钟
  • 如果我尝试使用
    CGImageRelease
    手动释放
    CGImageRef
    对象,则当图像尝试自动释放时,一分钟后会出现错误的执行异常
  • 使用
    CGImageRetain
    保留
    iref
    ,然后使用
    CGImageRelease
    释放它是不起作用的
  • 关于stackoverflow的类似问题没有帮助:

您应该保留CGImageRef


剩下的只是一个运行循环问题,在一个没有GCD的系统中,映像是随机发布的,在另一个系统中,映像是由GCD管理的,但无论如何都是错误的,必须有人拥有iref的所有权。

您应该保留CGImageRef


剩下的只是一个运行循环的问题,在一个没有GCD的系统中,映像是以静态方式发布的,在另一个系统中,映像是由GCD管理的,但无论如何都是错误的,必须有人取得iref的所有权。

首先,没有“自动删除”CF对象的概念。在处理免费桥接类时,您可能会遇到这样的情况,但正如您所看到的,有
CFRetain
CFRelease
但没有
CFAutorelease
。所以我认为你误解了
iref
的所有权。让我们在整个代码中跟踪所有权:

-(void)loadImage:(ALAsset*)asset{
资产
被传递到此方法中。假定其保留计数至少为1

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
块闭包在
资产
上进行保留

        @autoreleasepool {
            ALAssetRepresentation* rep = [asset defaultRepresentation];
            UIImage* image = [UIImage imageWithCGImage:iref
                                                 scale:[rep scale]
                                           orientation:UIImageOrientationUp];
通过命名约定,这将返回您不拥有的对象。它可能是自动释放的,也可能是单例/全局的,等等。但您不拥有它,也不应该通过保留它来获得它的所有权

            CGImageRef iref = [rep fullScreenImage];
由于没有“自动删除”CF对象的概念,我们假定
rep
正在返回一个指向
rep
拥有的
CGImageRef
的内部指针。你也不拥有它,也不应该保留它。与此相关的是,你无法控制它何时消失。一个合理的猜测是它的寿命与
rep
一样长,一个合理的猜测是
rep
的寿命与
asset
的寿命一样长,因此您可能应该假设
iref
的寿命至少与
asset
的寿命一样长

        @autoreleasepool {
            ALAssetRepresentation* rep = [asset defaultRepresentation];
            UIImage* image = [UIImage imageWithCGImage:iref
                                                 scale:[rep scale]
                                           orientation:UIImageOrientationUp];
如果UIImage需要CGImageRef保留,则需要保留或复制以确保其保持活动状态。(可能是后者)UIImage本身通过命名约定自动删除

            dispatch_async(dispatch_get_main_queue(), ^(void) {
此内部块闭合将在
图像
(和
自身
)上保留。libdispatch将复制该块,并延长这些保留的生命周期,直到执行该块并释放该块

                [self.imageView setImage:image];
如果需要,图像视图将在
图像
上保留(或复制)以执行其工作

            });
内部块执行完毕。在将来的某个时候,libdispatch将释放它,它将在
self
image
上通过块闭包传递释放保留

        }
你的自动释放池在这里弹出。任何隐式保留/自动删除的内容都应该立即发布

    });
外部块执行完毕。在将来的某个时候,libdispatch将释放它,这将过渡地释放
资产上的块闭包所获取的retain

}
最终,此方法无法控制
iref
中CGImageRef的生存期,因为它从未拥有它的所有权。这里的含义是CGImageRef是由
资产
过渡性拥有的,因此它的寿命至少与
资产
一样长。由于
asset
是通过在外部块中使用而保留的(即由外部块的闭包保留),并且由于libdispatch没有承诺何时释放完成的块,因此实际上无法保证
iref
会在libdispatch开始之前消失

如果您想转到手动保留/发布,并尽可能明确地说明,您可以这样做:

-(void)loadImage:(ALAsset*)asset{
    __block ALAsset* weakAsset = [asset retain]; // asset +1
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
        @autoreleasepool {
            ALAssetRepresentation* rep = [weakAsset defaultRepresentation];
            CGImageRef iref = [rep fullScreenImage];
            UIImage* image = [[UIImage alloc] imageWithCGImage:iref
                                                 scale:[rep scale]
                                           orientation:UIImageOrientationUp];

            __block UIImage* weakImage = [image retain]; // image +1

            [weakAsset release]; // asset -1

            dispatch_async(dispatch_get_main_queue(), ^(void) {
                [self.imageView setImage: weakImage];
                [weakImage release]; // image -1
            });
        }
    });
}
\uu block
防止块闭包保留
资产
图像
,允许您自己明确保留/释放它们。这意味着,在您创建的所有内容中,所有内容都将被显式地处理。(
rep
image
可能是保留/自动删除的,但您的池应该负责这些。)我相信这是您对此最明确的解释,因为
资产
是传递给您的,因此您无法控制它的寿命,它最终是“所有者”(就这个范围而言)存储在
iref
中的CGImageRef的


希望这能澄清一些问题。

首先,没有“自动删除”CF对象的概念。在处理免费桥接类时,您可能会遇到这样的情况,但正如您所看到的,有
CFRetain
CFRelease
但没有
CFAutorelease
。所以我认为你误解了
iref
的所有权。让我们在整个代码中跟踪所有权:

-(void)loadImage:(ALAsset*)asset{
资产
被传递到此方法中。假定其保留计数至少为1

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
块闭包在
资产
上进行保留

        @autoreleasepool {
            ALAssetRepresentation* rep = [asset defaultRepresentation];
            UIImage* image = [UIImage imageWithCGImage:iref
                                                 scale:[rep scale]
                                           orientation:UIImageOrientationUp];
通过命名修道院,这将返回您