使用__block变量阻止泄漏

时间:2015-03-12 02:42:35

标签: ios objective-c memory-leaks objective-c-blocks weak-references

我有一个很大的内存泄漏,我已经指出在requestContentEditingInputWithOptions:方法中发生。如果我理解正确的话会发生img变量。如果我将其设为__block __weak,则在我指定(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;
}

2 个答案:

答案 0 :(得分:4)

通过静态分析器运行此代码( shift + 命令 + 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);
        }
    }];
}

答案 1 :(得分:1)

罗布是对的钱。而且图像可能很大,这就是为什么你有大量泄漏的原因。核心基础对象的经验法则是“创建规则”。在Xcode上搜索“创建规则”并阅读文章。它的要点是:

  

Core Foundation函数的名称表明您拥有的时间   返回的对象:

     

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

     

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