- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我正在使用 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/
我正在拍摄屏幕照片并使用 UIGraphicsGetImageFromCurrentImageContext() 对其进行操作。一切都运转良好。然而,在 iPhone 4 上,分辨率看起来相当糟糕,因
UIGraphicsGetImageFromCurrentImageContext 返回自动释放的 UIImage。 想知道是否有办法从上下文中获取“分配”图像? 我想要等同于以下代码的东西,也许代码
我漏水了,但看不到哪里。 这是我的部分代码: + (UIImage *) imageWithColor:(UIColor *) color andSize:(CGSize) size { UI
我编写了以下代码片段来截取屏幕快照: UIGraphicsBeginImageContext(animationView.frame.size); [[window layer] renderInCo
UIImageView *cellimage = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0 , 107, 70)]; 我确信以上声明将在视网
我正在使用 UIImagePickerControllerSourceTypeCamera 和自定义 cameraOverlayView 打开相机,这样我就可以在没有“使用照片”步骤的情况下拍摄多张照
我想将一个 UIImage 分成两个单独的图像。我使用以下(有效)代码。 UIImage *splitMeInTwo = [UIImage imageNamed:@"Star.png"]; UIIma
我正在尝试在 PDF 中创建页面的预览图像但是我在释放内存时遇到了一些问题。 我写了一个简单的测试算法来循环这个问题,应用在第 40 次迭代附近崩溃: NSArray *paths = NSSearc
我正在尝试使用长按手势识别器重新排序 UITableView 单元格。当我从单元格表示层使用 UIGraphicsGetImageFromCurrentImageContext() 时,CAAnima
我试图理解,UIgraphicsGetImageContext() 函数,根据我的理解,它是一个函数,它从当前位图上下文中获取图像,所以每当我在 Canvas 上绘制一些东西并调用此函数时,我都会绘制
我想在我的应用程序中进行基本的照片编辑,现在我需要能够在照片上添加文本。原始照片的宽度和高度大于 2000 像素,因此将在不修改其比例的情况下缩放以适合屏幕。 因此,我将图像放在 UIImageVie
我有一个 UIView,用户可以在其中绘制各种 UIBezierPaths。 我需要分析绘制的 BezierPaths 来处理某些模式。我还没有找到任何将 UIBezierPaths 转换为坐标/点列
我试图了解我的代码在使用队列时崩溃的方式,但在使用主线程时却能正常工作。此代码运行良好: - (void)penMoved:(NSSet *)touches { UITouch *touch
在我的绘图应用程序中,我使用 UIImage 来缓存绘图。 以下代码行导致内存问题: UIGraphicsBeginImageContextWithOptions(self.bounds.size,
我有这个 UIImage 的扩展: extension UIImage { func resizeImage(newWidth: CGFloat, newHeight: CGFloat? = nil
我目前正在使用 UIGraphicsGetImageFromCurrentImageContext() 将内容的图像保存到用户的相机胶卷中,但图像质量比我在模拟器中进行屏幕截图时差。有什么办法可以改善
快速代码 当我们获取一个UIView的截图时,我们通常会使用这段代码: UIGraphicsBeginImageContextWithOptions(frame.size, false, scale)
我的 iPhone 应用程序从服务器下载图像文件,将其存储到 NSTemporaryDirectory() 中,然后在 UI 中异步加载图像。代码流程是这样的: 显示带有加载事件指示器的 View 并
好的,我正在拍摄用 iPhone 上的相机拍摄的照片的屏幕截图。我将相机照片放入 UIImageView 中,并使用此类代码抓取它的屏幕截图(来自 http://www.skylarcantu.com
我想以特定大小截取特定位置的屏幕截图。我找到了这个。但它需要整个屏幕。我在哪里可以设置 CGRect。 UIGraphicsBeginImageContext(self.window.bounds.s
我是一名优秀的程序员,十分优秀!