2009-08-27 5 views
7

Je sais que la méthode -imageNamed: renvoie un UIImage en cache, mais le problème est que mon fichier image est stocké dans 'Documents', et la méthode -imageNamed: semble chercher uniquement le paquet ... Je suis actuellement (à contrecoeur) en utilisant -imageWithContentsOfFile: pour obtenir mon image à partir de 'Documents' mais ce n'est pas pareil ... Mise à l'échelle haut/bas d'une UIImageView contenant l'image résultante est saccadée et maladroite. Mise à l'échelle de la même UIImageView contenant une image créée avec -imageNamed: cependant apparaît très lisse. Donc, encore une fois: Comment puis-je obtenir un UIImage en cache de mes 'Documents' si je ne peux pas utiliser -imageNamed :?Un moyen d'obtenir un UIImage en cache à partir de mon répertoire 'Documents'?

Répondre

4

Vous pouvez mettre en cache UIImages vous-même, tout comme -imageNamed:. Il les charge juste, et les retient ensuite. Vous pouvez les conserver également en utilisant un NSDictionary et implémentez le vôtre -imageNamed:

Mais je suis plus préoccupé par les problèmes que vous rencontrez avec la mise à l'échelle. Comment vos images entrent-elles dans Documents, comment les mettez-vous à l'échelle et avez-vous testé le même fichier image stocké dans le bundle? Je doute que -imageNamed: a quelque chose à voir avec cela. Je suspecterais des choses comme le fait que le bundle a une certaine compression appliquée (même si je n'ai pas encore de théorie sur les raisons pour lesquelles cela serait important en pratique), les différences dans le fichier, ou les différences dans la façon dont le programme se comporte pendant la mise à l'échelle (provoquant une contention sur le disque ou le processeur). La mise en cache est peu probable liée à ce problème.

Je ferais un profilage avec des instruments pour essayer de trouver d'où vient le clapotis. Êtes-vous maxing sur le disque, le processeur, la mémoire? Quel est le goulot d'étranglement?

+0

hmmm ... intéressant .. Je vais vérifier cela maintenant et revenir à vous. Merci – RexOnRoids

+0

J'ai résolu le problème mais je ne sais toujours pas quelle était la cause exacte. Les images qui évoluaient en douceur mesuraient 4 Ko, avaient des dimensions paires (puissance de 2) et étaient des fichiers PNG génériques, tandis que les images de taille variable avaient une taille de 200 Ko et étaient de dimensions irrégulières et étaient des fichiers PNG de type Adobe Fireworks. Une fois que j'ai réduit la taille du fichier, égalisé les dimensions, changé le type de fichier, tout a commencé à évoluer en douceur ... Qui sait pourquoi;) – RexOnRoids

1

Qu'en est-il de l'écriture de votre propre cache d'image? Vous avez toutes les pièces en place, maintenant vous avez juste besoin de l'encapsuler et de garder un enregistrement des images que vous avez déjà chargées.

8

La façon la plus simple serait un NSMutableDictionary stocker les images mises en cache et une méthode de cache claire:

@interface UIImage (CacheExtensions) 
+ (id)cachedImageWithContentsOfFile:(NSString *)path; 
+ (void)clearCache; 
@end 

static NSMutableDictionary *UIImageCache; 

@implementation UIImage (CacheExtensions) 
+ (id)cachedImageWithContentsOfFile:(NSString *)path 
{ 
    id result; 
    if (!UIImageCache) 
     UIImageCache = [[NSMutableDictionary alloc] init]; 
    else { 
     result = [UIImageCache objectForKey:path]; 
     if (result) 
      return result; 
    } 
    result = [UIImage imageWithContentsOfFile:path]; 
    [UIImageCache setObject:result forKey:path]; 
    return result; 
} 
+ (void)clearCache 
{ 
    [UIImageCache removeAllObjects]; 
} 
@end 

Remarque: vous devez appeler +[UIImage clearCache] de votre méthode didReceiveMemoryWarning. En outre, clearCache invalidera tous les objets dans le cache, pas seulement les éléments inutilisés; une sous-classe UIImage et un mécanisme de mise en cache plus compliqué seraient nécessaires pour y remédier.

+0

Nice, solution simple. +1 – iPadDeveloper2011

+0

Certainement, merci. +1 –

9

J'ai fait une extension de la réponse fournie par rpetrich et j'ai dépassé la méthode imageName: pour ajouter plus d'une goutte de remplacement. Il recherche d'abord le bundle principal puis regarde dans le répertoire des caches. Vous pouvez bien sûr changer le répertoire des caches dans le répertoire du document.

@interface UIImage (CacheExtensions) 
+ (UIImage *)imageNamed:(NSString *)name; 
+ (void)clearCache; 
@end 

#import "UIImage+CacheExtensions.h" 

static NSMutableDictionary *UIImageCache; 

@implementation UIImage (CacheExtensions) 

+ (UIImage *)imageNamed:(NSString *)name 
{ 
    id result; 
    if (!UIImageCache) 
     UIImageCache = [[NSMutableDictionary alloc] init]; 
    else { 
     result = [UIImageCache objectForKey:name]; 
     if (result) return result; 
    } 

    // First, check the main bundle for the image 
    NSString *imagePath = [[NSBundle mainBundle] pathForResource:name ofType:nil]; 

    result = [UIImage imageWithContentsOfFileimagePath]; 
    if(result) { 
     [UIImageCache setObject:result forKey:name]; 
     return result; 
    } 

    // If not found, search for the image in the caches directory 
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); 
    NSString *cachesImagePath = [[paths lastObject] stringByAppendingPathComponent:name]; 

    result = [UIImage imageWithContentsOfFile:cachesImagePath]; 
    if(result) { 
     [UIImageCache setObject:result forKey:name]; 
     return result; 
    } 

    return nil; 
} 

+ (void)clearCache 
{ 
    [UIImageCache removeAllObjects]; 
} 

@end 
+0

Génial! Mettre ceci à bon usage. :) –

+1

Vous ne devez pas remplacer les méthodes d'une catégorie. Utilisez simplement un nom différent. Voir ici: http://stackoverflow.com/a/5272612/921573 –

+0

Aussi, je recommanderais d'utiliser 'NSCache' au lieu de' NSMutableDictionary'. C'est là pour ça. –

Questions connexes