Получение сбоя после выбора изображений из UIImagePickerController (связано с утечкой памяти?)
Я пытался минимизировать мой след памяти сUIImagePickerController
, но я начинаю думать, что проблемы с памятью возникают из-за плохого управления памятью, а не из-за того, чтоUIImagePickerController
объект.
Мой рабочий процесс заключается в следующем: нажата кнопка «Изменить изображение», которая представляет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 в атрибуте отношений (Transformational, используя те же преобразования UIImage to PNG, которые были в демонстрационном коде Recipes) для использование отображения: (методы изменения размера основаны на показанном вэтот ТАК пост.)
- (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
, а также[object release]
в течениеdealloc
, но я все еще получаю предупреждения памяти после примерно 10 изменений изображения, с падением около 20. Это заставляет меня поверить, что я не получаю это полное изображение из памяти правильным способом. Что мне здесь не хватает?
И во-вторых, использует ли источник Camera значительно больше памяти, чем источник Photo Albums? Я имею тенденцию получать больше сбоев при использовании камеры.
--РЕДАКТИРОВАТЬ--Начиная щедрость длялюбой информация о том, что я могу неправильно обработать. Я буду обновлять этот пост любыми ответами на все, что мне неясно. Просто в конце моего ума на этом.
- EDIT 2--Переработан код, учитывающий предложения Криссра, и реализованGCD
улучшить удобство использования. Это так эффективно, как этот процесс? По-прежнему получают предупреждения памяти и сбой около 20 изображений. Я уверен, что сочетание делает дорогоUIImage
изменение размера и использованиеUIImagePickerController
убивает процессор, но я не могу себе представить, что каждое приложение имеет дело с неопределенностью вокруг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);
}