gpt4 book ai didi

ios - imageWithCGImage : GCD memory issue

转载 作者:行者123 更新时间:2023-12-01 17:18:23 24 4
gpt4 key购买 nike

当我仅在主线程 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: with GCD 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对象被分配并且在它应该被释放后仍然存在大约一分钟。
  • 如果我尝试手动释放 CGImageRef对象使用 CGImageRelease当图像尝试自动释放时,我在一分钟后收到 BAD_EXEC 异常。
  • 保留iref使用 CGImageRetain然后使用 CGImageRelease释放它不起作用。
  • 关于 stackoverflow 的类似问题没有帮助:image loading with gcd , received memory warning in create image , memory leak when get fullscreenimage from alaseet result ,
  • 最佳答案

    首先,没有“自动释放”CF 对象的概念。在处理免费桥接类(class)时,您可能会遇到这种情况,但正如您所见,有一个 CFRetainCFRelease但没有CFAutorelease .所以我认为你误解了 iref 的所有权。 .让我们在整个代码中跟踪所有权:

    -(void)loadImage:(ALAsset*)asset{
    asset被传递到这个方法中。假定其保留计数至少为 1。
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {

    闭包在 asset 上保留。 .
            @autoreleasepool {
    ALAssetRepresentation* rep = [asset defaultRepresentation];

    通过命名约定,这将返回一个您不拥有的对象。它可能是自动发布的,它可能是单例/全局的,等等。但你不拥有它,也不应该通过保留它来获得它的所有权。
                CGImageRef iref = [rep fullScreenImage];

    由于没有“自动释放”CF 对象的概念,我们假设 rep正在返回一个指向 CGImageRef 的内部指针归 rep 所有.你也不拥有它,也不应该保留它。相关地,您无法控制它何时会消失。一个合理的猜测是它的生命周期会和 rep 一样长。一个合理的猜测是 rep将活到 asset所以你可能应该假设 iref至少会活到 asset .
                UIImage* image = [UIImage imageWithCGImage:iref
    scale:[rep scale]
    orientation:UIImageOrientationUp];

    如果 UIImage 需要 CGImageRef 保持不变,它将进行保留或复制以确保它保持事件状态。 (可能是后者。)根据命名约定,UIImage 本身是自动释放的。
                dispatch_async(dispatch_get_main_queue(), ^(void) {

    这个内部 block 闭包将保留在 image 上。 (和 self )。该 block 将由 libdispatch 复制,以延长这些保留的生命周期,直到该 block 被执行并自行释放。
                    [self.imageView setImage:image];

    ImageView 将保留(或复制) image如果需要,为了完成它的工作。
                });

    内部 block 执行完毕。在 future 的某个时候,libdispatch 将释放它,这将传递地释放 self 上的 block 关闭所占用的保留。和 image .
            }

    你的自动释放池弹出在这里。任何被隐式保留/自动释放的东西现在都应该被释放。
        });

    外部 block 已完成执行。在 future 的某个时候,libdispatch 将释放它,这将传递地释放 asset 上的 block 关闭所占用的保留。 .
    }

    最终,此方法无法控制 iref 中 CGImageRef 的生命周期。因为它从不拥有它的所有权。这里的含义是 CGImageRef 由 asset 传递拥有。 , 所以它的生命周期至少和 asset 一样长.由于 asset由于在外部 block 中使用而被保留(即由外部 block 的闭包保留),并且由于 libdispatch 没有 promise 何时释放已完成的 block ,因此您实际上无法保证 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
    });
    }
    });
    }
    __block防止 block 关闭保留 assetimage允许您自己明确地保留/释放它们。这意味着在您创建的所有事物中,所有事物都将被显式处置。 ( repimage 可能是保留/自动释放,但你的池应该处理这些。)我相信这是你可以最明确的,因为 asset被传递给您,因此您无法控制它的生命周期,它最终是存储在 iref 中的 CGImageRef 的“所有者”(就这个范围而言) .

    希望能澄清一点。

    关于ios - imageWithCGImage : GCD memory issue,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19540713/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com