内存警告UIImagepickerController IOS 7

时间:2013-09-27 23:19:06

标签: ios memory-management uiimagepickercontroller ios7 didreceivememorywarning

任何人都可以帮我解决这个问题我对目标c和iOS有点新意。我一直在努力,但我无法弄清楚如何解决问题,我的应用程序非常简单,它只是启动相机拍照并通过电子邮件发送到我们的服务器。这段代码在iOS6中运行得很好。

当我拍照时,我的内存是每次屏幕捕获的堆增长,我得到“收到内存警告”,最后 - 由于内存压力终止。 -

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

[self.popoverController2 dismissPopoverAnimated:true];
NSString *mediaType = [info
                       objectForKey:UIImagePickerControllerMediaType];

if ([mediaType isEqualToString:(NSString *)kUTTypeImage]) {
    _image = [info
                      objectForKey:UIImagePickerControllerOriginalImage];

   _image = [self fixrotation:_image]; //<----- increased memory when UIImageWriteToSavedPhotosAlbum is uncommented IF is comment it doesn't increased memory but after some pictures I start to get "Received Memory Warning" message until the app Crash.

    if (_newMedia){
       UIImageWriteToSavedPhotosAlbum(_image,
                                       self,@selector(image:finishedSavingWithError:contextInfo:),
                                       nil);
    [self dismissViewControllerAnimated:NO completion:nil];
    [self performSegueWithIdentifier:@"SeleccionadoCameraR" sender:self];


    }else{
        [self performSegueWithIdentifier:@"SeleccionadoCameraR" sender:self];

    }

}

}

- (UIImage *)fixrotation:(UIImage *)image{


if (image.imageOrientation == UIImageOrientationUp) return image;
CGAffineTransform transform = CGAffineTransformIdentity;

switch (image.imageOrientation) {
    case UIImageOrientationDown:
    case UIImageOrientationDownMirrored:
        transform = CGAffineTransformTranslate(transform, image.size.width, image.size.height);
        transform = CGAffineTransformRotate(transform, M_PI);
        break;

    case UIImageOrientationLeft:
    case UIImageOrientationLeftMirrored:
        transform = CGAffineTransformTranslate(transform, image.size.width, 0);
        transform = CGAffineTransformRotate(transform, M_PI_2);
        break;

    case UIImageOrientationRight:
    case UIImageOrientationRightMirrored:
        transform = CGAffineTransformTranslate(transform, 0, image.size.height);
        transform = CGAffineTransformRotate(transform, -M_PI_2);
        break;
    case UIImageOrientationUp:
    case UIImageOrientationUpMirrored:
        break;
}

switch (image.imageOrientation) {
    case UIImageOrientationUpMirrored:
    case UIImageOrientationDownMirrored:
        transform = CGAffineTransformTranslate(transform, image.size.width, 0);
        transform = CGAffineTransformScale(transform, -1, 1);
        break;

    case UIImageOrientationLeftMirrored:
    case UIImageOrientationRightMirrored:
        transform = CGAffineTransformTranslate(transform, image.size.height, 0);
        transform = CGAffineTransformScale(transform, -1, 1);
        break;
    case UIImageOrientationUp:
    case UIImageOrientationDown:
    case UIImageOrientationLeft:
    case UIImageOrientationRight:
        break;
}

// Now we draw the underlying CGImage into a new context, applying the transform
// calculated above.
CGContextRef ctx = CGBitmapContextCreate(NULL, image.size.width, image.size.height,
                                         CGImageGetBitsPerComponent(image.CGImage), 0,
                                         CGImageGetColorSpace(image.CGImage),
                                         CGImageGetBitmapInfo(image.CGImage));


CGContextConcatCTM(ctx, transform);
switch (image.imageOrientation) {
    case UIImageOrientationLeft:
    case UIImageOrientationLeftMirrored:
    case UIImageOrientationRight:
    case UIImageOrientationRightMirrored:
        // Grr...
        CGContextDrawImage(ctx, CGRectMake(0,0,image.size.height,image.size.width), image.CGImage);
        break;

    default:
        CGContextDrawImage(ctx, CGRectMake(0,0,image.size.width,image.size.height), image.CGImage); //when I use instruments it shows that My VM is because of this 
        break;
}

// And now we just create a new UIImage from the drawing context
CGImageRef cgimg = CGBitmapContextCreateImage(ctx);//also this line in Instruments
UIImage *img = [UIImage imageWithCGImage:cgimg];


CGContextRelease(ctx);
CGImageRelease(cgimg);


return img;


 }

可能是内存管理。我将非常感谢您的帮助

3 个答案:

答案 0 :(得分:7)

您使用fixRotation方法走在正确的轨道上。但是,您还应调整大小图像。否则,图像将是巨大的,约30 MB(取决于设备)。

结帐this blog post,了解如何正确调整图片大小。具体来说,您需要的UIImage类别文件是:

UIImage+Resize.h

UIImage+Resize.m

在后台线程上执行此操作也是个好主意。像这样的东西

- (void)imagePickerController:(UIImagePickerController *)imagePicker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    // Dismiss the image picker first to free its memory
    [self dismissViewControllerAnimated:YES completion:nil];

    UIImage *originalImage = info[UIImagePickerControllerOriginalImage];

    if (!originalImage)
        return;

    // Optionally set a placeholder image here while resizing happens in background

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        // Set desired maximum height and calculate width
        CGFloat height = 640.0f;  // or whatever you need
        CGFloat width = (height / originalImage.size.height) * originalImage.size.width;

        // Resize the image
        UIImage * image = [originalImage resizedImage:CGSizeMake(width, height) interpolationQuality:kCGInterpolationDefault];

        // Optionally save the image here...

        dispatch_async(dispatch_get_main_queue(), ^{
            // ... Set / use the image here...
        });           
    });
}

答案 1 :(得分:4)

UIImageWriteToSavedPhotosAlbum方法在iOS7上使用30M +内存。这不是关于你的resize或fixrotation方法。

答案 2 :(得分:1)

我已经通过JRG-Developer-s解决了这个问题 稍作修改: 我正在使用类别来修复图像的方向,并在呈现之前将其缩小 完成后,我调用Weak Self将这个缩放和固定的图像分配给我的imageview)

-(void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{    
    UIImage *lvImage = [info objectForKey:UIImagePickerControllerOriginalImage];
    //CGSize pickedImageSize = lvImage.size;
    if (postHandler == nil)
    {
        postHandler = [[PostHandler alloc] init];
    }

    //_postItemImageView.image = lvImage;
    //postHandler.wholeScreenImage = lvImage;// to proceed editing, cropping, tagging ...
    //_postItemImageView.image = postHandler.wholeScreenImage; set in viewWillAppear
    __weak PostPrepareViewController *weakSelf = self;
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^
    {

        // Resize the image
        UIImage * scaledImage = [[lvImage imageByScalingAndCroppingForSize:_postItemImageView.frame.size] fixOrientation];
        // Optionally save the image here...
        //CGSize scaledimageSize = scaledImage.size;
        dispatch_async(dispatch_get_main_queue(), ^
        {
            postHandler.wholeScreenImage = scaledImage;
            [weakSelf didScaleDownImage];
        });           
    });


    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad)
    {
        [self.popOver dismissPopoverAnimated:YES];
    }
    else
    {
        [self dismissViewControllerAnimated:YES completion:nil];
    }
}

并降低:

-(void) didScaleDownImage
{
   _postItemImageView.image = postHandler.wholeScreenImage;
}

缩放代码来自网络:

-(UIImage *)imageByScalingAndCroppingForSize:(CGSize)targetSize
{
    UIImage *sourceImage = self;
    UIImage *newImage = nil;
    CGSize imageSize = sourceImage.size;
    CGFloat width = imageSize.width;
    CGFloat height = imageSize.height;
    CGFloat targetWidth = targetSize.width;
    CGFloat targetHeight = targetSize.height;
    CGFloat scaleFactor = 0.0;
    CGFloat scaledWidth = targetWidth;
    CGFloat scaledHeight = targetHeight;
    CGPoint thumbnailPoint = CGPointMake(0.0,0.0);

    if (CGSizeEqualToSize(imageSize, targetSize) == NO)
    {
        CGFloat widthFactor = targetWidth / width;
        CGFloat heightFactor = targetHeight / height;

        if (widthFactor > heightFactor)
        {
            scaleFactor = widthFactor; // scale to fit height
        }
        else
        {
            scaleFactor = heightFactor; // scale to fit width
        }

        scaledWidth  = width * scaleFactor;
        scaledHeight = height * scaleFactor;

        // center the image
        if (widthFactor > heightFactor)
        {
            thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5;
        }
        else
        {
            if (widthFactor < heightFactor)
            {
                thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5;
            }
        }
    }

    UIGraphicsBeginImageContext(targetSize); // this will crop
    //UIGraphicsBeginImageContextWithOptions(targetSize, 1.0, 0.0);

    CGRect thumbnailRect = CGRectZero;
    thumbnailRect.origin = thumbnailPoint;
    thumbnailRect.size.width  = scaledWidth;
    thumbnailRect.size.height = scaledHeight;

    [sourceImage drawInRect:thumbnailRect];

    newImage = UIGraphicsGetImageFromCurrentImageContext();

    if(newImage == nil)
    {
        NSLog(@"could not scale image");
    }

    //pop the context to get back to the default
    UIGraphicsEndImageContext();

    return newImage;
}

用于更改(修复)图像方向的代码也来自网络:

- (UIImage *)fixOrientation
{    // No-op if the orientation is already correct
    if (self.imageOrientation == UIImageOrientationUp) return self;

    // We need to calculate the proper transformation to make the image upright.
    // We do it in 2 steps: Rotate if Left/Right/Down, and then flip if Mirrored.
    CGAffineTransform transform = CGAffineTransformIdentity;

    switch (self.imageOrientation) {
        case UIImageOrientationDown:
        case UIImageOrientationDownMirrored:
            transform = CGAffineTransformTranslate(transform, self.size.width, self.size.height);
            transform = CGAffineTransformRotate(transform, M_PI);
            break;

        case UIImageOrientationLeft:
        case UIImageOrientationLeftMirrored:
            transform = CGAffineTransformTranslate(transform, self.size.width, 0);
            transform = CGAffineTransformRotate(transform, M_PI_2);
            break;

        case UIImageOrientationRight:
        case UIImageOrientationRightMirrored:
            transform = CGAffineTransformTranslate(transform, 0, self.size.height);
            transform = CGAffineTransformRotate(transform, -M_PI_2);
            break;

        default:
            break;
    }

    switch (self.imageOrientation) {
        case UIImageOrientationUpMirrored:
        case UIImageOrientationDownMirrored:
            transform = CGAffineTransformTranslate(transform, self.size.width, 0);
            transform = CGAffineTransformScale(transform, -1, 1);
            break;

        case UIImageOrientationLeftMirrored:
        case UIImageOrientationRightMirrored:
            transform = CGAffineTransformTranslate(transform, self.size.height, 0);
            transform = CGAffineTransformScale(transform, -1, 1);
            break;

        default:
            break;
    }

    // Now we draw the underlying CGImage into a new context, applying the transform
    // calculated above.
    CGContextRef ctx = CGBitmapContextCreate(NULL, self.size.width, self.size.height,
                                             CGImageGetBitsPerComponent(self.CGImage), 0,
                                             CGImageGetColorSpace(self.CGImage),
                                             CGImageGetBitmapInfo(self.CGImage));
    CGContextConcatCTM(ctx, transform);
    switch (self.imageOrientation) {
        case UIImageOrientationLeft:
        case UIImageOrientationLeftMirrored:
        case UIImageOrientationRight:
        case UIImageOrientationRightMirrored:
            // Grr...
            CGContextDrawImage(ctx, CGRectMake(0,0,self.size.height,self.size.width), self.CGImage);
            break;

        default:
            CGContextDrawImage(ctx, CGRectMake(0,0,self.size.width,self.size.height), self.CGImage);
            break;
    }

    // And now we just create a new UIImage from the drawing context
    CGImageRef cgimg = CGBitmapContextCreateImage(ctx);
    CGContextRelease(ctx);
    UIImage *img = [UIImage imageWithCGImage:cgimg];

    CGImageRelease(cgimg);
   //
    return img;
}

拜托,如果看起来像假的东西,请不要吝啬。我现在很小便)

下面的答案 - 这就是为什么你要更好地缩小图像 - 为了减少使用中的内存,而不是简单地将大4MB图像保存到光盘。在一开始我也有记忆问题 - 每张照片吃30Mb - 而且我不得不逐张拍摄2张照片......现在它工作得非常顺畅。 修正方向是可选的,但我建议无论如何缩小照片 - 将其调整为较小的尺寸。