2016-06-17 18 views
1

Ich möchte UIImage in NSArray zu lokal als PNG speichern. Wenn ich jedoch UIImagePNGRepresentation in einer For-Schleife verwendete, wuchs der Speicher stark, obwohl es bereits einen @autoreleasepool gibt.UIImage speichern in PNG verursachen Speicherverlust

for (int i = 0; i < array.count; i++) { 

    @autoreleasepool { 
     NSDictionary *src = array[i]; 

     NSString *localPath = [SPLDPath stringByAppendingPathComponent:@"realImg"]; 
     NSFileManager *file = [NSFileManager defaultManager]; 
     if (![file fileExistsAtPath:localPath]) { 
      [file createDirectoryAtPath:localPath withIntermediateDirectories:NO attributes:nil error:nil]; 
     } 

     NSString *screenShotImg = [localPath stringByAppendingPathComponent:[NSString stringWithFormat:@"ScreenShot_%d.png", i]]; 
     NSData *PNGData = UIImagePNGRepresentation(src[@"image"]); 
     [PNGData writeToFile:screenShotImg atomically:YES]; 
    } 
} 

Also habe ich versucht UIImage zu CGImageRef und verwenden ImageIO Framework Bild zu speichern zu konvertieren. Verwenden Sie dann CGImageRelease(), um den Speicher in jeder Schleife freizugeben.

-(void)saveImage:(CGImageRef)image directory:(NSString*)directory filename:(NSString*)filename { 
@autoreleasepool { 
    CFURLRef url = (__bridge CFURLRef)[NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/%@", directory, filename]]; 
    CGImageDestinationRef destination = CGImageDestinationCreateWithURL(url, kUTTypePNG, 1, NULL); 
    CGImageDestinationAddImage(destination, image, nil); 

    if (!CGImageDestinationFinalize(destination)) 
     NSLog(@"ERROR saving: %@", url); 

    CFRelease(destination); 
    CGImageRelease(image); 
} 

}

for (int i = 0; i < array.count; i++) { 

    NSDictionary *src = array[i]; 

    NSString *localPath = [SPLDPath stringByAppendingPathComponent:@"realImg"]; 
     NSFileManager *file = [NSFileManager defaultManager]; 
    if (![file fileExistsAtPath:localPath]) { 
     [file createDirectoryAtPath:localPath withIntermediateDirectories:NO attributes:nil error:nil]; 
    } 
    NSString *fileName = [NSString stringWithFormat: @"ScreenShot_%d.png", i]; 

    CGImageRef cgRef=[src[@"image"] CGImage]; 
    [self saveImage:(cgRef) directory:localPath filename:fileName]; 

} enter image description here Der Speicher verringert wurde, jedoch geschah ein neues Thema. Meine App ist aufgrund von zu viel freigegebenem Speicher abgestürzt. Weil der UIImage von CGImageRelease() veröffentlicht wurde, aber ARC auch versuchte, eine delloc-Nachricht an das Zombie-Objekt zu senden, bevor die App beendet wurde. Wie kann ich CGImageRef freigeben, aber nicht mit ARC kollidieren?

Antwort

0

Rufen Sie CGImageRelease() nicht für die CGImage-Eigenschaft auf, da Ihr Code keine Inkr ref für dieses Objekt enthält. Sie würden in diesem Fall nur dann freigeben, wenn Ihr Code die Ref-Stelle explizit inkrementiert hätte.

+0

THX für Ihre Antwort. Aber wenn ich den CGImageRef nicht freigegeben habe, wird der Speicher weiter wachsen, was kann ich tun, um Speicher in jeder Schleife freizugeben? –

+0

Der Code, den Sie oben veröffentlichten, versucht, mit CGImageRelease() zu veröffentlichen, wenn das Bild nicht gehalten wird. Beheben Sie das zuerst und dann die anderen Probleme in Ihrem Code. Zum Beispiel können Sie einfach einen Dateinamen in eine Methode übergeben, diese Logik das PNG laden lassen und dann alle gehaltenen Referenzen freigeben. Im Gegensatz zu dem, was Sie jetzt tun, das alle dekomprimierten PNG-Bilder im Speicher hält. Sie können einfach nicht viele dekomprimierte Bilder gleichzeitig im Speicher halten. Behebe das und du solltest besser dran sein. – MoDJ