获取内存泄漏 - NSData转换

时间:2016-06-21 05:12:53

标签: ios objective-c nsdata

我正在通过以下方案获取iPhone 4的内存压力警告: 我需要将我的图像上传到服务器并使用亚马逊s3。我正在使用以下代码将我选择的图像转换为NSMutableData

CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)imageData, NULL);

CFDictionaryRef options = (__bridge CFDictionaryRef)@{(id)kCGImageSourceCreateThumbnailWithTransform: (id)kCFBooleanTrue,
                                                      (id)kCGImageSourceCreateThumbnailFromImageIfAbsent: (id)kCFBooleanTrue,
                                                      (id)kCGImageSourceThumbnailMaxPixelSize: [NSNumber numberWithDouble: maxSize],
                                                      (id)kCGImageDestinationLossyCompressionQuality: [NSNumber numberWithDouble:compressionQuality]};

CGImageRef thumbnail = CGImageSourceCreateThumbnailAtIndex(source, 0, options); // Create scaled image

CFStringRef UTI = kUTTypeJPEG;
NSMutableData *destData = [NSMutableData data];
CGImageDestinationRef destination = CGImageDestinationCreateWithData((__bridge CFMutableDataRef)destData, UTI, 1, NULL);
if (!destination) {
    NSLog(@"Failed to create image destination");
}
CGImageDestinationAddImage(destination, thumbnail,( __bridge CFDictionaryRef)metadata); // copy all metadata in source to destination
if (!CGImageDestinationFinalize(destination)) {
    NSLog(@"Failed to create data from image destination");
}

if (!destination) CFRelease(destination);
CFRelease(source);
CFRelease(thumbnail);

return [destData copy];

为什么在循环执行此操作后第24个图像后会出现内存警告?

2 个答案:

答案 0 :(得分:2)

此代码有泄漏。

具体来说,您有一行说:

if (!destination) CFRelease(destination);

仅当它是NULL时才会释放它,这与你想要的相反:

if (destination) CFRelease(destination);

顺便说一句,如果按 shift + 命令 + B ,Xcode将对您的代码执行静态分析。它会告诉你这个问题(以及代码中的一些其他问题)。找到这些问题非常好。

我可能会建议:

- (NSData * _Nullable)processImageData:(NSData *)imageData maxSize:(double)maxSize compressionQuality:(double)compressionQuality metadata:(NSDictionary *)metadata {
    CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)imageData, NULL);

    CFDictionaryRef options = (__bridge CFDictionaryRef)@{(id)kCGImageSourceCreateThumbnailWithTransform: (id)kCFBooleanTrue,
                                                          (id)kCGImageSourceCreateThumbnailFromImageIfAbsent: (id)kCFBooleanTrue,
                                                          (id)kCGImageSourceThumbnailMaxPixelSize: [NSNumber numberWithDouble: maxSize],
                                                          (id)kCGImageDestinationLossyCompressionQuality: [NSNumber numberWithDouble:compressionQuality]};

    CGImageRef thumbnail = CGImageSourceCreateThumbnailAtIndex(source, 0, options); // Create scaled image

    CFRelease(source);

    CFStringRef UTI = kUTTypeJPEG;
    NSMutableData *destData = [NSMutableData data];
    CGImageDestinationRef destination = CGImageDestinationCreateWithData((__bridge CFMutableDataRef)destData, UTI, 1, NULL);
    if (!destination) {
        NSLog(@"Failed to create image destination");
        destData = nil;
    } else {
        CGImageDestinationAddImage(destination, thumbnail,(__bridge CFDictionaryRef)metadata); // copy all metadata in source to destination
        if (!CGImageDestinationFinalize(destination)) {
            NSLog(@"Failed to create data from image destination");
            destData = nil;
        }
        CFRelease(destination);
    }

    CFRelease(thumbnail);

    return [destData copy];
}

答案 1 :(得分:0)

当您将此图像作为整体加载到内存中时,它会引起内存问题。通常我会将图像保存到Document目录,然后使用图像的PATH通过multipart上传图像。 这只会将图像加载为多部分,因此内存问题不会成为问题。我不知道这是否适用于您正在做的事情。

请告诉我。