我一直在尝试最小化我的内存占用UIImagePickerController
,但我开始认为我遇到的内存问题是由于内存管理不善造成的,而不是处理内存问题的特定方法UIImagePickerController
object.
我的工作流程是这样的:单击“编辑图像”按钮,它会显示一个UIActionSheet
。此操作表允许您删除、拍照、从库中选择或取消。如果您选择从库中选择或拍照,我alloc
的一个实例UIImagePickerController
并展示它,然后发布UIImagePickerController
:
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (actionSheet.tag != 999) {
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
imagePicker.delegate = self;
BOOL pickImage = nil;
if (actionSheet.tag == iPhoneWithDelete) {
switch (buttonIndex) {
case 0:
object.objectImage = nil;
pickImage = NO;
break;
case 1:
imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
pickImage = YES;
break;
case 2:
imagePicker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
pickImage = YES;
break;
default:
pickImage = NO;
break;
}
} else if (actionSheet.tag == iPhoneNoDelete) {
switch (buttonIndex) {
case 0:
imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
pickImage = YES;
break;
case 1:
imagePicker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
pickImage = YES;
break;
default:
pickImage = NO;
break;
}
} else if (actionSheet.tag == iPodWithDelete) {
switch (buttonIndex) {
case 0:
object.objectImage = nil;
pickImage = NO;
break;
case 1:
imagePicker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
pickImage = YES;
break;
default:
pickImage = NO;
break;
}
} else if (actionSheet.tag == iPodNoDelete) {
switch (buttonIndex) {
case 0:
imagePicker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
pickImage = YES;
break;
default:
pickImage = NO;
break;
}
}
if (pickImage) {
imagePicker.allowsEditing = YES;
[self presentModalViewController:imagePicker animated:YES];
} else {
[self setupImageButton];
[self setupChooseImageButton];
}
[imagePicker release];
}
}
一旦我从UIImagePickerController
,我将 2 个图像、用于缩略图的已编辑图像的调整大小版本以及原始未编辑图像的 800x600 版本保存到关系属性中(转换,使用在食谱演示代码中找到的相同 UIImage 到 PNG 转换)显示使用:(调整大小方法基于中演示的方法这个帖子.)
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
[self dismissModalViewControllerAnimated:YES];
NSManagedObject *oldImage = object.imageFull;
if (oldImage != nil)
{
[object.managedObjectContext deleteObject:oldImage];
}
NSManagedObject *image = [NSEntityDescription insertNewObjectForEntityForName:@"Image" inManagedObjectContext:object.managedObjectContext];
object.imageFull = image;
UIImage *rawImage = [info objectForKey:@"UIImagePickerControllerOriginalImage"];
CGSize size = CGSizeMake(800, 600);
UIImage *fullImage = [UIImageManipulator scaleImage:rawImage toSize:size];
[image setValue:fullImage forKey:@"imageFull"];
UIImage *processedImage = [UIImageManipulator scaleImage:[info objectForKey:@"UIImagePickerControllerEditedImage"] toSize:CGSizeMake(75, 75)];
object.objectImage = processedImage;
[self setupImageButton];
[self setupChooseImageButton];
rawImage = nil;
fullImage = nil;
processedImage = nil;
}
当我经过viewDidUnload
我正在设置self.object = nil
, and [object release]
during dealloc
,但在大约 10 次图像更改后,我仍然收到内存警告,并在 20 次左右发生崩溃。这让我相信我没有以正确的方式从内存中获取完整图像。我在这里缺少什么?
其次,相机源使用的内存是否比相册源使用的内存多得多?我在使用相机时往往会发生更多崩溃。
--EDIT--
开始赏金any有关我可能处理错误的信息。我将用任何我不清楚的问题的答案来更新这篇文章。我对此无计可施。
--编辑2--
重新编写代码以考虑 chrissr 的建议并实施GCD
以提高可用性。这个过程是否如此高效?仍然收到内存警告,并且大约 20 个图像崩溃。我确信做昂贵的组合UIImage
调整大小和使用UIImagePickerController
正在谋杀 CPU,但我无法想象每个应用程序都在处理围绕 CPU 的不确定性UIImagePickerController
。我的内存占用约为 2 兆。我一直假设这会产生大量开销。我应该进一步减少足迹吗?
这是修改后的代码:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
[self dismissModalViewControllerAnimated:YES];
if (object.imagePath != nil) {
[self deleteImages];
}
dispatch_queue_t image_queue;
image_queue = dispatch_queue_create("com.gordonfontenot.app", NULL);
dispatch_async(image_queue, ^{
NSDate *now = [NSDate date];
NSDateFormatter *f = [[NSDateFormatter alloc] init];
[f setDateFormat:@"yyyyMMDDHHmmss"];
NSString *imageName = [NSString stringWithFormat:@"Image-%@-%i", [f stringFromDate:now], arc4random() % 100];
NSString *thumbName = [NSString stringWithFormat:@"%@-thumb", imageName];
[f release];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *fullPath = [documentsDirectory stringByAppendingPathComponent:imageName];
NSString *thumbPath = [documentsDirectory stringByAppendingPathComponent:thumbName];
NSData *thumbImageData = UIImagePNGRepresentation([UIImageManipulator scaleImage:[info objectForKey:@"UIImagePickerControllerEditedImage"] toSize:CGSizeMake(120, 120)]);
[thumbImageData writeToFile:thumbPath atomically:NO];
dispatch_async(dispatch_get_main_queue(), ^{
object.thumbPath = thumbPath;
[self setupImageButton];
imageButton.enabled = NO;
[self setupChooseImageButton];
});
NSData *fullImageData = UIImagePNGRepresentation([UIImageManipulator scaleImage:[info objectForKey:@"UIImagePickerControllerOriginalImage"] toSize:CGSizeMake(800, 600)]);
[fullImageData writeToFile:fullPath atomically:NO];
dispatch_async(dispatch_get_main_queue(), ^{
imageButton.enabled = YES;
object.imagePath = fullPath;
});
if (picker.sourceType == UIImagePickerControllerSourceTypeCamera) {
UIImageWriteToSavedPhotosAlbum([info objectForKey:@"UIImagePickerControllerOriginalImage"], self, nil, nil);
}
});
dispatch_release(image_queue);
}