Frage

Februar 2014 bearbeiten: Beachten Sie, dass diese Frage aus iOS 2.0 stammt! Die Bildanforderungen und die Handhabung haben sich seitdem stark weiterentwickelt. Retina macht Bilder größer und laden sie etwas komplexer. Mit der integrierten Unterstützung für iPad- und Retina -Bilder, Sie sollten sicherlich im Bildstand in Ihrem Code verwenden.

Ich sehe viele Leute sagen imageNamed ist schlecht, aber die gleiche Anzahl von Menschen, die sagen, dass die Leistung gut ist - besonders beim Rendern UITableViews. Sehen Diese Frage Zum Beispiel oder Dieser Artikel auf iPhoneSevelopertips.com

UIImage's imageNamed Die Methode zum Leckern, so dass sie am besten vermieden wurde, wurde aber in den letzten Veröffentlichungen festgelegt. Ich würde gerne den Caching -Algorithmus besser verstehen, um eine begründete Entscheidung darüber zu treffen, wo ich dem System vertrauen kann, um meine Bilder zu zwischenstrahlen und wohin ich die Extrameile gehen und es selbst tun muss. Mein aktuelles grundlegendes Verständnis ist, dass es einfach ist NSMutableDictionary von UIImages auf den Dateinamen verwiesen. Es wird größer und wenn das Gedächtnis ausgeht, wird es viel kleiner.

Weiß beispielsweise jemand sicher, dass der Bildcache dahinter steht? imageNamed reagiert nicht auf didReceiveMemoryWarning? Es ist unwahrscheinlich, dass Apple dies nicht tun würde.

Wenn Sie einen Einblick in den Caching -Algorithmus haben, posten Sie ihn bitte hier.

War es hilfreich?

Lösung

TLDR: ImagedNamed ist in Ordnung. Es behandelt die Erinnerung gut. Verwenden Sie es und hören Sie auf, sich Sorgen zu machen.

November 2012 bearbeiten: Beachten Sie, dass diese Frage aus iOS 2.0 stammt! Die Bildanforderungen und die Handhabung haben sich seitdem stark weiterentwickelt. Retina macht Bilder größer und laden sie etwas komplexer. Mit der eingebauten Unterstützung für iPad- und Retina -Bilder sollten Sie sicherlich in Ihrem Code imagedierten verwenden. Nun, um die Nachwelt willen:

Das Schwester -Thread In den Apple Dev -Foren erhielt er einen besseren Verkehr. Speziell Rincewind etwas Autorität hinzugefügt.

Es gibt Probleme in iPhone OS 2.x, bei denen der Imagedamed: Cache auch nach einer Speicherwarnung nicht gelöscht wird. Gleichzeitig +Imagedamed: Hat nicht für den Cache, sondern für die Bequemlichkeit viel verwendet, was das Problem wahrscheinlich mehr vergrößert hat, als es hätte sein sollen.

während warnt das

Auf der Geschwindigkeitsfront gibt es ein allgemeines Missverständnis darüber, was vor sich geht. Das Größte, was +imagEnamed: TO -Dekodierung die Bilddaten aus der Quelldatei, die fast immer die Datengröße erheblich aufblasen (z. B. eine PNG -Datei mit Bildschirmgröße könnte beim Komprimieren ein paar Dutzend KBs konsumieren, aber mehr als eine halbe MB konsumiert dekomprimiert - Breite * Höhe * 4). Im Gegensatz dazu dekomprimieren Sie dieses Bild jedes Mal, wenn die Bilddaten benötigt werden. Wie Sie sich vorstellen können, wenn Sie die Bilddaten nur einmal benötigen, haben Sie hier nichts gewonnen, außer um eine zwischengespeicherte Version des Bildes zu haben und wahrscheinlich länger als Sie es brauchen. Wenn Sie jedoch ein großes Bild haben, das Sie häufig neu zeichnen müssen, gibt es Alternativen, obwohl ich in erster Linie empfehlen würde, dieses große Bild neu zu zeichnen :).

In Bezug auf das allgemeine Verhalten des Cache wird der Cache basierend auf Dateinamen (so zwei Instanzen von +bildendemed: Mit demselben Namen sollten zu Verweise auf dieselben zwischengespeicherten Daten führen) und der Cache wächst dynamisch, wenn Sie mehr Bilder über mehr Bilder anfordern +imagedamed:. Auf iPhone OS 2.XA -Fehler verhindert, dass der Cache beim Eingang einer Speicherwarnung geschrumpft wird.

und

Mein Verständnis ist, dass der +imagEnamed: Cache Speicherwarnungen auf iPhone OS 3.0 respektieren sollte. Testen Sie es, wenn Sie eine Chance erhalten und Fehler melden, wenn Sie feststellen, dass dies nicht der Fall ist.

Also, da hast du es. Imagedamed: Wird Ihre Fenster nicht zerschlagen oder Ihre Kinder ermorden. Es ist ziemlich einfach, aber es ist ein Optimierungswerkzeug. Leider ist es schlecht benannt und es gibt kein Äquivalentum, das so einfach zu bedienen ist - daher überbeanspruchen die Leute es und ärgern sich, wenn es einfach seinen Job macht

Ich habe UIImage eine Kategorie hinzugefügt, um das zu beheben:

// header omitted
// Before you waste time editing this, please remember that a semi colon at the end of a method definition is valid and a matter of style.
+ (UIImage*)imageFromMainBundleFile:(NSString*)aFileName; {
    NSString* bundlePath = [[NSBundle mainBundle] bundlePath];
    return [UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"%@/%@", bundlePath,aFileName]];
}

RinceWind enthielt auch einen Beispielcode, um eine eigene optimierte Version zu erstellen. Ich kann nicht sehen, dass es die Wartung wert ist, aber hier ist es für Vollständigkeit.

CGImageRef originalImage = uiImage.CGImage;
CFDataRef imageData = CGDataProviderCopyData(
     CGImageGetDataProvider(originalImage));
CGDataProviderRef imageDataProvider = CGDataProviderCreateWithCFData(imageData);
CFRelease(imageData);
CGImageRef image = CGImageCreate(
     CGImageGetWidth(originalImage),
     CGImageGetHeight(originalImage),
     CGImageGetBitsPerComponent(originalImage),
     CGImageGetBitsPerPixel(originalImage),
     CGImageGetBytesPerRow(originalImage),
     CGImageGetColorSpace(originalImage),
     CGImageGetBitmapInfo(originalImage),
     imageDataProvider,
     CGImageGetDecode(originalImage),
     CGImageGetShouldInterpolate(originalImage),
     CGImageGetRenderingIntent(originalImage));
CGDataProviderRelease(imageDataProvider);
UIImage *decompressedImage = [UIImage imageWithCGImage:image];
CGImageRelease(image);

Der Kompromiss mit diesem Code ist, dass das dekodierte Bild mehr Speicher verwendet, aber das Rendering schneller ist.

Andere Tipps

In my experience, the image cache created by imageNamed does not respond to memory warnings. I've had two applications that were as lean as I could get them as far as mem management, but were still inexplicably crashing due to lack of mem. When I stopped using imageNamed to load the images, both applications became dramatically more stable.

I will admit that both applications loaded somewhat large images, but nothing that would be totally out of the ordinary. In the first application, I just skipped caching altogether because it was unlikely a user would come back to the same image twice. In the second, I built a really simple caching class doing just what you mentioned - keeping UIImages in an NSMutableDictionary and then flushing its contents if I received a memory warning. If imageNamed: were to cache like that, then I shouldn't have seen any performance upgrade. All of this was running on 2.2 - I don't know if there's any 3.0 implications on this.

You can find my other question around this issue from my first app here: StackOverflow question about UIImage cacheing

One other note - InterfaceBuilder uses imageNamed under the covers. Something to keep in mind if you do run into this problem.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top