2014-07-12 7 views
0

je être diagnostiquées ai le code suivant choisi de réponses sur StackOverflow:Redimensionner une image dans iOS - fuite

+ (UIImage *)resizeImage:(UIImage *)image toSize:(CGSize)newSize; 
{ 
    // UIGraphicsBeginImageContext(newSize); 
    // In next line, pass 0.0 to use the current device's pixel scaling factor (and thus account for Retina resolution). 
    // Pass 1.0 to force exact pixel size. 

    UIGraphicsBeginImageContextWithOptions(newSize, NO, 1.0); 
    [image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)]; 
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 
    return newImage; 
} 

J'utilise cela comme une catégorie pour le type UIImage. Je le suis de profilage dans la méthode suivante:

+ (void)testResize:(UIImage *)image 
{ 
    clock_t start = clock(); 
    int times = 50; 
    for (int i = 0; i < 50; i++) { 
     // resize photo 
     UIImage *resizedImage = [UIImage resizeImageToOptimalSize:image]; 
     resizedImage = nil; 
    } 
    double diff = (double)clock()-start; 
    printf("testResize = %f\n", diff * 1000/times/CLOCKS_PER_SEC); 
} 

Peu importe si je modifie le code ci-dessus et de vidage juste le resizeImageToOptimalSize appel 50 fois, je vois le profileur va noix. Voici le code resizeImageToOptimalSize juste au cas où vous vous demandez, je fait une erreur ici:

+ (UIImage *)resizeImageToOptimalSize:(UIImage *)image 
{ 
    CGSize newSize = CGSizeMake(..., ...); 
    return [self resizeImage:image toSize:newSize]; 
} 

L'augmentation de l'utilisation de la mémoire et monte et descend ensuite ~ 1.5MB lorsque la méthode se termine. Voici la capture d'écran d'instruments:

Instruments screenshot for <code>resizePhoto</code> running on iPhone 4S

Il n'y a pas de fuite en soi de l'outil Instruments mais je ne le crois pas. C'est soit la boucle for ne pas lâcher resizedImage ou si quelque chose se passe avec le contexte (pas sûr).

Répondre

1

Vous devez ajouter @autoreleasepool à l'intérieur de la boucle for.

for (int i = 0; i < 50; i++) { 
    @autoreleasepool { 
      // resize photo 
      UIImage *resizedImage = [UIImage resizeImageToOptimalSize:image]; 
     } 
    } 

De même, vous n'avez pas besoin de définir resizedImage sur nil. L'image est auto-libérée (au moins sans optimisations).

+0

Pouvez-vous expliquer plus en détail pourquoi je dois mettre ceci dans un bloc 'autoreleasepool'? – p0lAris

+0

L'image est renvoyée en tant qu'objet auto-libéré, mais le pool ajouté ne peut pas être drainé tant que la fonction n'est pas terminée. Vous devez utiliser le pool autorelease dans les boucles serrées comme ceci ou renommer la méthode à quelque chose comme newResizedImage afin qu'ARC renvoie l'objet "possédé" (il devrait y avoir aussi un qualificateur pour cela, mais je ne m'en souviens pas). –