UIGraphicsGetImageFromCurrentImageContext () - Przeciek pamięci

Otwieram aparat za pomocąUIImagePickerControllerSourceTypeCamera i zwyczajcameraOverlayView więc mogę robić wiele zdjęć bez kroku „Użyj zdjęcia”.

Działa to doskonale, ale w funkcji zapisywania zdjęć występuje przeciek pamięci. Dzięki wielu debugowaniu i badaniom zawęziłem go doUIGraphicsGetImageFromCurrentImageContext funkcjonować.

Oto fragment kodu, w którym to się dzieje:

UIGraphicsBeginImageContextWithOptions(timestampedImage.frame.size, timestampedImage.opaque, [[UIScreen mainScreen] scale]);
[[timestampedImage layer] renderInContext:UIGraphicsGetCurrentContext()];
UIImage *finalTimestampImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

Przeszukałem internet i wygląda na to, żeUIGraphicsGetImageFromCurrentImageContext() funkcja (cytowana zto pytanie TAK) „zwraca nowy autoreleasedUIImage i wskazujefinalTimestampImage ivar do tego. Poprzednio przydzieloneUIImage nigdy nie jest faktycznie zwolniony, zmienna do niego jest po prostu przypisywana do innego miejsca. ”

Próbowałem tak wielu rozwiązań, które najwyraźniej zadziałały dla innych:

DodawanietimestampedImage.layer.contents = nil; poUIGraphicsEndImageContext

DodawanieCGContextRef context = UIGraphicsGetCurrentContext(); iCGContextRelease(context); poUIGraphicsEndImageContext

Zawijanie powyższego fragmentu wNSAutoreleasePool

Zawijanie całegosaveThisPhoto funkcja wNSAutoreleasePool

TworzenieNSAutoreleasePool kiedy aparat wyskoczy i zadzwoni do[pool release] gdydidReceiveMemoryWarning jest nazywany

Zamykanie okienka kamery, gdydidReceiveMemoryWarning jest wywoływany, mając nadzieję, że wyczyści pulę

Każda możliwa kombinacja powyższych

Jednak wszystko, co próbuję, kiedy robię zdjęcia, widzęMemory Utilized rośnie i nie spada, gdy wielokrotnie robię zdjęcia na urządzeniu.

Czy ktoś wie, w jaki sposób mogę uwolnić obiekt autorelease stworzony przezUIGraphicsGetImageFromCurrentImageContext?

Alternatywnie, istnieje alternatywny sposób wykonaniaUIImage zUIImageView?

Edytować:

Oto pełne funkcje na żądanie. Jest tam wiele dodatkowych wydań, aby się upewnićwszystko jest oczyszczony. Przeszedłem i przetestowałem przeciek pamięci przy każdym bloku kodusaveThisPhoto systematycznie i występuje tylko wtedy, gdyUIGraphicsGetImageFromCurrentImageContext Uruchomiony jest blok (fragment powyżej).

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

    NSLog(@"SAVING PHOTO");

    [self saveThisPhoto:info];

    picker = nil;
    [picker release];

    info = nil;
    [info release];

}

- (void)saveThisPhoto:(NSDictionary *)info {

    // Get photo count for filename so we're not overriding photos

    int photoCount = 0;

    if ([[NSUserDefaults standardUserDefaults] objectForKey:@"photocount"]) {
        photoCount= [[[NSUserDefaults standardUserDefaults] objectForKey:@"photocount"] intValue];
        photoCount++;
    }

    [[NSUserDefaults standardUserDefaults] setObject:[NSString stringWithFormat:@"%d", photoCount] forKey:@"photocount"];
    [[NSUserDefaults standardUserDefaults] synchronize];

    // Obtaining saving path

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *fileName = [NSString stringWithFormat:@"ri_%d.jpg", photoCount];
    NSString *fileNameThumb = [NSString stringWithFormat:@"ri_%d_thumb.jpg", photoCount];
    NSString *imagePath = [documentsDirectory stringByAppendingPathComponent:fileName];
    NSString *imagePathThumb = [documentsDirectory stringByAppendingPathComponent:fileNameThumb];

    // Extracting image from the picker and saving it

    NSString *mediaType = [info objectForKey:UIImagePickerControllerMediaType];

    // SAVE TO IPAD AND DB

    if ([mediaType isEqualToString:@"public.image"]){

        // Get Image

        UIImage *editedImage = [info objectForKey:UIImagePickerControllerOriginalImage];

        // Figure out image orientation

        CGSize resizedSize;
        CGSize thumbSize;

        if (editedImage.size.height > editedImage.size.width) {
            resizedSize = CGSizeMake(480, 640);
            thumbSize = CGSizeMake(150, 200);
        } else {
            resizedSize = CGSizeMake(640, 480);
            thumbSize = CGSizeMake(150, 113);
        }

        // MAKE NORMAL SIZE IMAGE

        UIImage *editedImageResized = [editedImage resizedImage:resizedSize interpolationQuality:0.8];

        // clean up the one we won't use any more

        editedImage = nil;
        [editedImage release];

        // ADD TIMESTAMP TO IMAGE

        // make the view

        UIImageView *timestampedImage = [[UIImageView alloc] initWithImage:editedImageResized];
        CGRect thisRect = CGRectMake(editedImageResized.size.width - 510, editedImageResized.size.height - 30, 500, 20);

        // clean up

        editedImageResized = nil;
        [editedImageResized release];

        // make the label

        UILabel *timeLabel = [[UILabel alloc] initWithFrame:thisRect];
        timeLabel.textAlignment =  UITextAlignmentRight;
        timeLabel.textColor = [UIColor yellowColor];
        timeLabel.backgroundColor = [UIColor clearColor];
        timeLabel.font = [UIFont fontWithName:@"Arial Rounded MT Bold" size:(25.0)];
        timeLabel.text = [self getTodaysDateDatabaseFormat];
        [timestampedImage addSubview:timeLabel];

        // clean up what we won't use any more

        timeLabel = nil;
        [timeLabel release];

        // make UIIMage out of the imageview -- MEMORY LEAK LOOKS LIKE IT IS IN THIS BLOCK

        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

        UIGraphicsBeginImageContextWithOptions(timestampedImage.frame.size, timestampedImage.opaque, [[UIScreen mainScreen] scale]);
        [[timestampedImage layer] renderInContext:UIGraphicsGetCurrentContext()];
        UIImage *finalTimestampImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        timestampedImage.layer.contents = nil;
        CGContextRef context = UIGraphicsGetCurrentContext();
        CGContextRelease(context);

        // clean up the one we won't use any more

        timestampedImage = nil;
        [timestampedImage release];

        // SAVE NORMAL SIZE IMAGE TO DOCUMENTS FOLDER

        NSData *webDataResized = UIImageJPEGRepresentation(finalTimestampImage, 1.0); // JPG

        [webDataResized writeToFile:imagePath atomically:YES];

        // clean up the one we won't use any more

        finalTimestampImage = nil;
        [finalTimestampImage release];

        [pool release]; // to get rid of the context image that is stored

        // SAVE TO DATABASE

        [sqlite executeNonQuery:@"INSERT INTO inspection_images (agentid,groupid,inspectionid,areaid,filename,filenamethumb,filepath,orderid,type) VALUES (?, ?, ?, ?, ?, ?, ?, ?,?) ",
         [NSNumber numberWithInt:loggedIn],
         [NSNumber numberWithInt:loggedInGroup],
         myInspectionID,
         [[tableData objectAtIndex:alertDoMe] objectForKey:@"areaid"],
         fileName,
         fileNameThumb,
         documentsDirectory,
         [NSNumber numberWithInt:photoCount],
         [NSNumber numberWithInt:isPCR]
         ];

        // Clean up

        webDataResized = nil;
        [webDataResized release];

    } else {

        NSLog(@">>> IMAGE ***NOT*** SAVED");

    }

    NSLog(@"IMAGE SAVED - COMPLETE");

    info = nil;
    [info release];

}

questionAnswers(1)

yourAnswerToTheQuestion