65 votes

Différence entre [UIImage imageNamed...] et [UIImage imageWithData...]?

Je veux charger des images dans mon application à partir du système de fichiers. Il y a 2 façons faciles de le faire :

[UIImage imageNamed:fullFileName]

ou :

NSString *fileLocation = [[NSBundle mainBundle] pathForResource:fileName ofType:extension];
NSData *imageData = [NSData dataWithContentsOfFile:fileLocation];

[UIImage imageWithData:imageData];

Je préfère la première méthode car c'est beaucoup moins de code, mais j'ai vu certaines personnes dire que l'image est mise en cache et que cette méthode utilise plus de mémoire ? Comme je ne fais pas confiance aux gens sur la plupart des autres forums, j'ai pensé poser la question ici, y a-t-il une différence pratique, et si oui laquelle est 'meilleure'?

J'ai essayé de profiler mon application en utilisant l'instrument Object Allocation, et je ne vois aucune différence pratique, bien que je n'aie essayé que dans le simulateur, et pas sur un iPhone lui-même.

91voto

Marc Charbonneau Points 30464

Il 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 va aider à la gestion de la mémoire. Par exemple, si vous chargez une image 10 fois pour l'afficher avec du texte dans une vue de tableau, UIImage ne conservera qu'une seule représentation de cette image en mémoire au lieu d'allouer 10 objets séparés. D'un autre côté, si vous avez une très grande image et que vous ne la réutilisez pas, vous voudrez peut-être 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'énormes images, je ne m'en inquiéterais pas. À moins que vous ne rencontriez un problème (et bravo pour avoir vérifié l'Allocation d'Objet au lieu d'optimiser de manière préventive), je choisirais moins de lignes de code pour des améliorations de mémoire négligeables.

10voto

Hunter Points 2827

Dans mon expérience [UIImage imageNamed:] a des performances nettement meilleures, surtout lorsqu'il est utilisé dans des UITableViews.

Il ne s'agit pas seulement de la mémoire mais aussi du décodage de l'image. L'avoir mis en cache est beaucoup plus rapide.

10voto

Monjer Points 329

Comme le référence de l'API UIImage le dit :

+(UIImage *)imageNamed:(NSString *)name

Cette méthode recherche dans les caches système un objet image avec le nom spécifié et renvoie cet objet s'il existe. Si un objet image correspondant n'est pas déjà dans le cache, cette méthode charge les données de l'image depuis le fichier spécifié, les met en cache, puis renvoie l'objet résultant.

+(UIImage *)imageWithContentsOfFile:(NSString *)path

Cette méthode ne met pas en cache l'objet image.

Ainsi, nous pouvons voir que si vous avez beaucoup des mêmes éléments UI (comme UITableViewCell) qui peuvent utiliser la même image (souvent comme des icônes), et en raison des performances, bien sûr nous voulons réutiliser la même image, afin d'économiser de la mémoire pour d'autres utilisations. Généralement, l'image réutilisée est souvent utilisée dans l'élément d'interface utilisateur sur lequel notre utilisateur peut effectuer beaucoup de fois. Donc il est important pour nous de la réutiliser. Vous pouvez donc choisir d'utiliser la méthode imageNamed.

D'autre part, dans une application, il y aura certains éléments d'interface utilisateur qui seront là pendant le cycle de vie de l'application, comme un bouton, une vue de logo, donc ces images utilisées par ces éléments d'interface utilisateur peuvent également être là pendant le cycle de vie de l'application, vous ne vous demanderiez pas si ces images doivent être mises en cache ou non. Vous pouvez donc choisir d'utiliser la méthode imageNamed.


Par contre, dans une application, il y a souvent certains éléments d'interface utilisateur qui sont créés dynamiquement. Par exemple, notre application supporte un fond d'écran dynamique, afin que l'utilisateur puisse choisir le fond d'écran qu'il aime. Et le fond d'écran peut être une image. Donc nous pouvons avoir une interface qui liste beaucoup de différents fonds d'écran (souvent affichés par une utilisation de UIImageView) pour que l'utilisateur choisisse, nous pouvons nommer la vue de liste MyBackgroundListView. Donc une fois que l'utilisateur choisit un fond d'écran, le MyBackgroundListView devrait être détruit, car il a terminé sa fonction. La prochaine fois que l'utilisateur souhaite changer son fond d'écran, nous pouvons recréer MyBackgroundListView. Donc les images utilisées par MyBackgroundListView ne devraient pas être mises en cache, sinon la mémoire de notre application sera épuisée. Cette fois, vous devriez utiliser la méthode imageWithContentsOfFile.

Comme le dit la documentation d'Apple Prise en charge des écrans haute résolution dans les vues

Sur les appareils avec des é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. Si elle en trouve une, elle charge cette image à la place. Si vous ne fournissez pas une version haute résolution d'une image donnée, l'objet image charge quand même une image à résolution standard (si une existe) et la met à l'échelle pendant le dessin.

Vous devriez donc vous inquiéter du problème du chemin de recherche de l'image pour les écrans Retina. IOS vous aidera à gérer cela.

Désolé pour mon mauvais anglais. Peut-être utile.

7voto

CedricSoubrie Points 3008

Si vous ne voulez pas que votre image soit mise en cache, vous pouvez également utiliser initWithContentsOfFile directement :

NSString *fileLocation = [[NSBundle mainBundle] pathForResource:fileName ofType:extension];
UIImage* yourImage = [[[UIImage alloc] initWithContentsOfFile:imagePath] autorelease];

5voto

Ben Gottlieb Points 59900

On m'a également dit que [UIImage imageNamed:] fait un peu trop de mise en cache, et que les images ne sont pas souvent libérées. On m'a dit d'être prudent en l'utilisant.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X