Je souhaite charger des images dans mon application à partir du système de fichiers. Il y a 2 façons simples de faire cela:
[UIImage imageNamed:fullFileName]
ou:
NSString *fileLocation = [[NSBundle mainBundle] pathForResource:fileName ofType:extension];
NSData *imageData = [NSData dataWithContentsOfFile:fileLocation];
[UIImage imageWithData:imageData];
Je préfère le premier parce que c'est beaucoup moins de code, mais j'ai vu des gens dire que l'image est mise en cache et que cette méthode utilise plus de mémoire? Puisque je ne fais pas confiance aux gens sur la plupart des autres forums, je me suis dit que je poserais la question suivante: existe-t-il une différence pratique et, dans l'affirmative, lequel est le meilleur?
J'ai essayé de profiler mon application à l'aide de l'instrument Object Allocation et je ne vois aucune différence pratique, même si je n'ai essayé que dans le simulateur et non sur un iPhone.
Cela dépend de ce que vous faites avec l'image. La méthode imageNamed:
met en cache l'image, mais dans de nombreux cas, cela facilitera l'utilisation de la mémoire. Par exemple, si vous chargez une image à afficher 10 fois avec du texte dans une vue sous forme de tableau, UIImage ne conservera qu'une seule représentation de cette image en mémoire au lieu d'allouer 10 objets distincts. D'autre part, si vous avez une très grande image et que vous ne la réutilisez pas, vous pouvez charger l'image à partir d'un objet de données pour vous assurer qu'elle est supprimée de la mémoire lorsque vous avez terminé.
Si vous n'avez pas d'images énormes, je ne m'en soucierais pas. À moins que vous ne voyiez un problème (et des félicitations pour la vérification de l'allocation d'objets au lieu de l'optimisation anticipée), je choisirais moins de lignes de code par rapport aux améliorations de mémoire négligeables.
D'après mon expérience, [UIImage imageNamed:]
a des performances nettement meilleures, notamment lorsqu'il est utilisé dans UITableViews
.
Ce n'est pas seulement la mémoire mais aussi le décodage de la image
. La mise en cache est beaucoup plus rapide.
Comme le dit la référence API de UIImage:
+ (UIImage *) imageNamed: (NSString *) name
Cette méthode recherche dans les caches système un objet image portant le nom spécifié et renvoie cet objet s'il existe. Si un objet image correspondant ne se trouve pas déjà dans le cache, cette méthode charge les données d'image à partir du fichier spécifié, les met en cache, puis renvoie l'objet résultant.
+ (UIImage *) imageWithContentsOfFile: (NSString *) chemin
Cette méthode ne met pas en cache l'objet image.
ainsi, nous pouvons voir que si vous avez beaucoup d'éléments UI identiques (tels que UITableViewCell) pouvant utiliser la même image (souvent sous la forme d'un icônes), et en raison des performances, nous souhaitons bien sûr réutiliser le même image, de sorte que nous allons économiser de la mémoire pour une autre utilisation. De manière générale, l'image réutilisée est souvent utilisée dans l'élément d'interface utilisateur que notre utilisateur peut utiliser beaucoup de fois. Il est donc important pour nous de le réutiliser. Pour que vous puissiez utiliser la méthode imageNamed.
D'autre part, dans une application, il y aura un élément UI qui sera présent pendant le cycle de vie de l'application, tel qu'un bouton, une vue de logo, de sorte que ces images utilisées par ces éléments ui peuvent également être utilisées. pendant le cycle de vie de l'application, vous ne voudriez pas que ces images soient en cache ou non. Vous pouvez donc choisir d'utiliser la méthode imageNamed.
Au contraire, dans une application, il y a souvent des UI Elements qui sont créés dynamiquement. Par exemple, notre application supporte background dynamique, de sorte que l’utilisateur puisse choisir l’arrière-plan qu’il aime. Et le background peut être une image. Nous pouvons donc avoir une interface qui répertorie de nombreux background (souvent montré en utilisant UIImageView) à choisir par l'utilisateur, nous pouvons nommer la vue liste MyBackgroundListView .Pour que l'utilisateur choisisse un arrière-plan image, le MyBackgroundListView doit être détruit, car il a terminé sa fonction. La prochaine fois que l'utilisateur souhaite modifier son arrière-plan, nous pouvons créer à nouveau MyBackgroundListView .Par conséquent, le images utilisé par MyBackgroundListView mis en cache, sinon la mémoire de notre application s’épuisera. Pour cette fois, vous devez utiliser la méthode imageWithContentsOfFile.
Comme le document Apple Prise en charge des écrans haute résolution dans Views dit
Sur les périphériques dotés d'écrans haute résolution, les méthodes imageNamed:, imageWithContentsOfFile: et initWithContentsOfFile: recherchent automatiquement une version de l'image demandée avec le modificateur @ 2x dans son nom. S'il en trouve un, il charge cette image à la place. Si vous ne fournissez pas de version haute résolution d'une image donnée, l'objet image charge tout de même une image à résolution standard (s'il en existe une) et la redimensionne pendant le dessin.
vous vous inquiéteriez donc du chemin de recherche de l'image pour le problème d'écran de la rétine. IOS vous aidera à le gérer.
Désolé pour mon mauvais anglais . Peut-il être utile.
Si vous ne voulez pas que votre image soit mise en cache, vous pouvez également utiliser directement initWithContentsOfFile:
NSString *fileLocation = [[NSBundle mainBundle] pathForResource:fileName ofType:extension];
UIImage* yourImage = [[[UIImage alloc] initWithContentsOfFile:imagePath] autorelease];
On m'a également dit que [UIImage imageNamed:]
fait un peu trop de cache et que les images ne sont pas publiées. On m'a dit de faire attention à l'utiliser.
imageWithData est utile lorsque vous stockez votre image binaire dans une base de données ou que vous téléchargez progressivement une image de grande taille à partir du Web.
Je ne voudrais pas utiliser imagenamed si votre application contient des tonnes de grandes images qui ne sont pas identiques. J'ai rencontré une application qui plantait parce que j'en utilisais trop.