繁体   English   中英

使用__block变量阻止泄漏

[英]Block leak with __block variable

我发现在requestContentEditingInputWithOptions:方法中/上发生了很大的内存泄漏。 如果我理解正确,它将与img变量一起发生。 如果我将其设置为__block __weak ,则在分配图像后该图像__block __weak nil (img = [UIImage...]) 我在某个地方傻吗? 还是我将如何避免这种内存泄漏?

- (UIImage*) getRightlySizedImgFromAsset:(PHAsset*)asset {

    __block UIImage *img;


    PHContentEditingInputRequestOptions *coptions = [PHContentEditingInputRequestOptions new];
    coptions.canHandleAdjustmentData = ^BOOL(PHAdjustmentData *adjustmentData) { return NO; };

    //semaphore used so the block runs synchronously and I can return img from this method at the end
    dispatch_semaphore_t sem = dispatch_semaphore_create(0);

    [asset requestContentEditingInputWithOptions:coptions completionHandler:^(PHContentEditingInput *contentEditingInput, NSDictionary *info) {
        NSURL* url = [contentEditingInput fullSizeImageURL];
        int orientation = [contentEditingInput fullSizeImageOrientation];

        CIImage* inputImage = [CIImage imageWithContentsOfURL:url options:nil];
        inputImage = [inputImage imageByApplyingOrientation:orientation];
        CIContext *context = [CIContext contextWithOptions:nil];

        img = [UIImage imageWithCGImage:[context createCGImage:inputImage fromRect:inputImage.extent]];

        dispatch_semaphore_signal(sem);
    }];
    dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);


    if (needToDoSomethingWithImg){
        [self doSomethingWithImage:img];
    }


    return img;
}

通过静态分析器运行此代码( shift + command + B或从“产品”菜单中选择“分析”),这将指出createCGImage正在创建您永远不会释放的CGImageRef

您可能想要执行以下操作:

CGImageRef imageRef = [context createCGImage:inputImage fromRect:inputImage.extent];
img = [UIImage imageWithCGImage:imageRef];
CFRelease(imageRef);

顺便说一句,您不应该同步执行此操作。 您应该执行以下操作:

- (void) getRightlySizedImgFromAsset:(PHAsset*)asset completionHandler:(void (^)(UIImage *))completionHandler {

    PHContentEditingInputRequestOptions *coptions = [PHContentEditingInputRequestOptions new];
    coptions.canHandleAdjustmentData = ^BOOL(PHAdjustmentData *adjustmentData) { return NO; };

    [asset requestContentEditingInputWithOptions:coptions completionHandler:^(PHContentEditingInput *contentEditingInput, NSDictionary *info) {
        NSURL* url = [contentEditingInput fullSizeImageURL];
        int orientation = [contentEditingInput fullSizeImageOrientation];

        CIImage* inputImage = [CIImage imageWithContentsOfURL:url options:nil];
        inputImage = [inputImage imageByApplyingOrientation:orientation];
        CIContext *context = [CIContext contextWithOptions:nil];

        CGImageRef imageRef = [context createCGImage:inputImage fromRect:inputImage.extent];
        UIImage *image = [UIImage imageWithCGImage:imageRef];
        CFRelease(imageRef);

        // if this stuff needs to happen on main thread, then dispatch it to the main thread

        if (needtodosomethingwithit)
            [self doSomethingWithImage:image];

        if (completionHandler) {
            completionHandler(image);
        }
    }];
}

罗伯是对的。 图像可能很大,所以这就是泄漏大的原因。 Core Foundation对象的经验法则是“创建规则”。 在“创建规则”的Xcode中搜索并阅读该文章。 要点是:

Core Foundation函数的名称指示您何时拥有返回的对象:

名称中嵌入“创建”的对象创建函数;

在名称中嵌入了“复制”的对象复制功能。 如果您拥有一个对象,则有责任在完成使用后放弃所有权(使用CFRelease)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM