10

Ai đó có thể giúp tôi về vấn đề này, tôi hơi mới với mục tiêu c và iOS. Tôi đã làm việc trên nó nhưng tôi không thể tìm ra cách để khắc phục vấn đề, ứng dụng của tôi thực sự đơn giản nó chỉ bắt đầu camera chụp ảnh và gửi chúng qua email đến máy chủ của chúng tôi. Mã này hoạt động tốt trong iOS6.Cảnh báo bộ nhớ UIImagepickerController IOS 7

Khi chụp ảnh, bộ nhớ của tôi tăng trưởng heap với mỗi lần chụp màn hình và tôi nhận được "Cảnh báo bộ nhớ đã nhận" và cuối cùng - Chấm dứt do áp lực bộ nhớ. -

-(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; 


} 

có lẽ là quản lý bộ nhớ. Tôi sẽ đánh giá cao sự giúp đỡ của bạn

+0

Chạy trình phân tích tĩnh để xem có cảnh báo nào không. Sau đó chạy ứng dụng trong Công cụ và tìm kiếm bất kỳ rò rỉ nào và giữ lại chu kỳ. – rmaddy

Trả lời

7

Bạn đang đi đúng hướng với phương pháp fixRotation của mình. Tuy nhiên, bạn cũng nên đổi kích thước hình ảnh. Nếu không, hình ảnh sẽ rất lớn, ~ 30 MB (tùy thuộc vào thiết bị).

Thanh toán this blog post cách thay đổi kích thước hình ảnh chính xác. Cụ thể, UIImage file thư mục mà bạn muốn là những:

UIImage+Resize.h

UIImage+Resize.m

Nó cũng là một ý tưởng tốt để làm điều này trên một sợi nền. Một cái gì đó như thế này

- (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... 
     });   
    }); 
} 
+0

Tôi đã thay đổi kích thước, tăng bộ nhớ, nhưng nó vẫn tiếp tục tăng chậm hơn một chút cho đến khi ứng dụng của tôi bị hỏng, bằng cách nào đó tôi cần làm sạch bộ nhớ –

+0

Trước hết tôi đã nói một dự án mới với iOS7 với cùng Lớp và phương pháp và cuối cùng Tôi đã thay đổi kích thước hình ảnh thành 640 x 480 và 480 X 640 và sau đó tôi áp dụng phương pháp fixRotation, bộ nhớ của tôi tăng một lần nhưng với các ảnh khác thì không. –

+0

@cesartrujillocetina Bạn có thể hiển thị mã làm việc cuối cùng của mình không? Tôi đang gặp vấn đề tương tự. – Danpe

4

phương pháp UIImageWriteToSavedPhotosAlbum sử dụng 30M + bộ nhớ trên iOS7.It không phải về thay đổi kích thước hoặc fixrotation phương pháp.

+0

Tôi có cùng một vấn đề và thay đổi kích thước hình ảnh doens't làm việc ... – Ladessa

+0

Tôi cũng có cùng một vấn đề .. là bất kỳ ai có giải pháp? – Sabareesh

+0

Có người đàn ông, mỗi khi tôi gọi UIImageWriteToSavedPhotosAlbum ứng dụng của tôi nhận được cảnh báo bộ nhớ !! Và rõ ràng là sụp đổ! –

1

Tôi đã cố định vấn đề này bằng JRG-Developer-s câu trả lời lên đây với một thay đổi nhỏ: I `m sử dụng loại để sửa chữa định hướng hình ảnh ANS rộng nó xuống trước khi trình bày và khi thực hiện xong, tôi gọi Yếu Tự để gán hình ảnh thu nhỏ lại và cố định này để ImageView tôi)

-(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]; 
    } 
} 

và thấp hơn:

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

quy tắc ứng rộng được lấy từ lưới:

-(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; 
} 

và mã để thay đổi (sửa chữa) định hướng hình ảnh cũng được lấy từ lưới:

- (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; 
} 

xin vui lòng, don-t là độc ác trong minusing nếu một cái gì đó trông dummy) Im junior cho bây giờ)

Đối với câu trả lời dưới đây - đó là lý do tại sao bạn nên quy mô tốt hơn một hình ảnh - để mất ít bộ nhớ hơn, nhưng không chỉ đơn giản là lưu hình ảnh 4MB lớn vào đĩa. Lúc đầu tôi cũng đã có vấn đề về bộ nhớ - nó đã ăn 30Mb mỗi ảnh sigle - và tôi phải chụp 2 bức ảnh từng cái một ... bây giờ nó hoạt động tốt và mượt mà. Sửa định hướng là tùy chọn, nhưng tôi khuyên bạn nên giảm kích thước ảnh xuống - thay đổi kích thước của ảnh thành nhỏ hơn.