gpt4 book ai didi

ios - UIGraphicsGetImageFromCurrentImageContext() - 内存泄漏

转载 作者:可可西里 更新时间:2023-11-01 03:34:30 25 4
gpt4 key购买 nike

我正在使用 UIImagePickerControllerSourceTypeCamera 和自定义 cameraOverlayView 打开相机,这样我就可以在没有“使用照片”步骤的情况下拍摄多张照片。

这很好用,但保存照片功能存在内存泄漏。通过大量调试和研究,我将其缩小到 UIGraphicsGetImageFromCurrentImageContext 函数。

这是它发生的一段代码:

UIGraphicsBeginImageContextWithOptions(timestampedImage.frame.size, timestampedImage.opaque, [[UIScreen mainScreen] scale]);
[[timestampedImage layer] renderInContext:UIGraphicsGetCurrentContext()];
UIImage *finalTimestampImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

我在互联网上搜索了一下,似乎 UIGraphicsGetImageFromCurrentImageContext() 函数(引自 this SO question)“返回一个新的自动发布的 UIImage 并指向finalTimestampImage 分配给它。之前分配的 UIImage 从未真正释放,它的变量只是重新指向其他地方。“

我已经尝试了很多显然对其他人有效的解决方案:

  • UIGraphicsEndImageContext

    之后添加 timestampedImage.layer.contents = nil;
  • UIGraphicsEndImageContext

    之后添加 CGContextRef context = UIGraphicsGetCurrentContext();CGContextRelease(context);
  • 将上面的代码片段包装在 NSAutoreleasePool

  • 将整个 saveThisPhoto 函数包装在 NSAutoreleasePool

  • 在相机弹出时创建一个NSAutoreleasePool,并在调用didReceiveMemoryWarning时调用[pool release]

  • 在调用 didReceiveMemoryWarning 时关闭相机弹出窗口,希望它能清除池

  • 以上所有可能的组合

然而我尝试的一切,当我拍照时,当我在设备上重复拍照时,我可以看到 Memory Utilized 上升而不是下降。

有谁知道如何释放 UIGraphicsGetImageFromCurrentImageContext 创建的自动释放对象?

或者,是否有另一种方法可以从 UIImageView 制作 UIImage

编辑:

这里是所要求的全部功能。那里添加了很多额外的版本,只是为了确保一切都被清理干净。我已经系统地检查并测试了 saveThisPhoto 中每个代码块的内存泄漏,它仅在运行 UIGraphicsGetImageFromCurrentImageContext block (上面的代码片段)时发生。

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {

NSLog(@"SAVING PHOTO");

[self saveThisPhoto:info];

picker = nil;
[picker release];

info = nil;
[info release];

}

- (void)saveThisPhoto:(NSDictionary *)info {

// Get photo count for filename so we're not overriding photos

int photoCount = 0;

if ([[NSUserDefaults standardUserDefaults] objectForKey:@"photocount"]) {
photoCount= [[[NSUserDefaults standardUserDefaults] objectForKey:@"photocount"] intValue];
photoCount++;
}

[[NSUserDefaults standardUserDefaults] setObject:[NSString stringWithFormat:@"%d", photoCount] forKey:@"photocount"];
[[NSUserDefaults standardUserDefaults] synchronize];

// Obtaining saving path

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *fileName = [NSString stringWithFormat:@"ri_%d.jpg", photoCount];
NSString *fileNameThumb = [NSString stringWithFormat:@"ri_%d_thumb.jpg", photoCount];
NSString *imagePath = [documentsDirectory stringByAppendingPathComponent:fileName];
NSString *imagePathThumb = [documentsDirectory stringByAppendingPathComponent:fileNameThumb];

// Extracting image from the picker and saving it

NSString *mediaType = [info objectForKey:UIImagePickerControllerMediaType];

// SAVE TO IPAD AND DB

if ([mediaType isEqualToString:@"public.image"]){

// Get Image

UIImage *editedImage = [info objectForKey:UIImagePickerControllerOriginalImage];

// Figure out image orientation

CGSize resizedSize;
CGSize thumbSize;

if (editedImage.size.height > editedImage.size.width) {
resizedSize = CGSizeMake(480, 640);
thumbSize = CGSizeMake(150, 200);
} else {
resizedSize = CGSizeMake(640, 480);
thumbSize = CGSizeMake(150, 113);
}

// MAKE NORMAL SIZE IMAGE

UIImage *editedImageResized = [editedImage resizedImage:resizedSize interpolationQuality:0.8];

// clean up the one we won't use any more

editedImage = nil;
[editedImage release];

// ADD TIMESTAMP TO IMAGE

// make the view

UIImageView *timestampedImage = [[UIImageView alloc] initWithImage:editedImageResized];
CGRect thisRect = CGRectMake(editedImageResized.size.width - 510, editedImageResized.size.height - 30, 500, 20);

// clean up

editedImageResized = nil;
[editedImageResized release];

// make the label

UILabel *timeLabel = [[UILabel alloc] initWithFrame:thisRect];
timeLabel.textAlignment = UITextAlignmentRight;
timeLabel.textColor = [UIColor yellowColor];
timeLabel.backgroundColor = [UIColor clearColor];
timeLabel.font = [UIFont fontWithName:@"Arial Rounded MT Bold" size:(25.0)];
timeLabel.text = [self getTodaysDateDatabaseFormat];
[timestampedImage addSubview:timeLabel];

// clean up what we won't use any more

timeLabel = nil;
[timeLabel release];

// make UIIMage out of the imageview -- MEMORY LEAK LOOKS LIKE IT IS IN THIS BLOCK

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

UIGraphicsBeginImageContextWithOptions(timestampedImage.frame.size, timestampedImage.opaque, [[UIScreen mainScreen] scale]);
[[timestampedImage layer] renderInContext:UIGraphicsGetCurrentContext()];
UIImage *finalTimestampImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
timestampedImage.layer.contents = nil;
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextRelease(context);

// clean up the one we won't use any more

timestampedImage = nil;
[timestampedImage release];

// SAVE NORMAL SIZE IMAGE TO DOCUMENTS FOLDER

NSData *webDataResized = UIImageJPEGRepresentation(finalTimestampImage, 1.0); // JPG

[webDataResized writeToFile:imagePath atomically:YES];

// clean up the one we won't use any more

finalTimestampImage = nil;
[finalTimestampImage release];

[pool release]; // to get rid of the context image that is stored

// SAVE TO DATABASE

[sqlite executeNonQuery:@"INSERT INTO inspection_images (agentid,groupid,inspectionid,areaid,filename,filenamethumb,filepath,orderid,type) VALUES (?, ?, ?, ?, ?, ?, ?, ?,?) ",
[NSNumber numberWithInt:loggedIn],
[NSNumber numberWithInt:loggedInGroup],
myInspectionID,
[[tableData objectAtIndex:alertDoMe] objectForKey:@"areaid"],
fileName,
fileNameThumb,
documentsDirectory,
[NSNumber numberWithInt:photoCount],
[NSNumber numberWithInt:isPCR]
];

// Clean up

webDataResized = nil;
[webDataResized release];

} else {

NSLog(@">>> IMAGE ***NOT*** SAVED");

}

NSLog(@"IMAGE SAVED - COMPLETE");

info = nil;
[info release];

}

最佳答案

您在释放变量之前将变量设置为 nil,有些变量已经自动释放。

通常在使用 release 时你应该 release 并将它们设置为 nil。

[var release]
var = nil;

但是在其中一些中你不应该调用 release。

以下是您的罪魁祸首。

    // clean up the one we won't use any more

timestampedImage = nil;
[timestampedImage release];

// SAVE NORMAL SIZE IMAGE TO DOCUMENTS FOLDER

关于ios - UIGraphicsGetImageFromCurrentImageContext() - 内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19967460/

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