2009-08-27 17 views
7

So che il metodo -imageNamed: restituisce un UIImage memorizzato nella cache, ma il problema è che il mio file immagine è memorizzato in "Documenti", e il metodo -imageNamed: sembra cercare solo nel pacchetto ... Sono attualmente (con riluttanza) usando -imageWithContentsOfFile: per ottenere la mia immagine da 'Documenti' ma non è la stessa ... Ridimensionare su/giù una UIImageView contenente l'immagine risultante è instabile e scomoda. Scalare lo stesso UIImageView contenente un'immagine creata con -imageNamed: tuttavia appare molto scorrevole. Quindi, ancora: Come posso ottenere un UIIimmagine memorizzata nella cache dal mio "Documenti" se non riesco a usare -imageNamed :?Qualche modo per ottenere un oggetto UII memorizzato nella cache dalla mia directory "Documenti"?

risposta

4

È possibile memorizzare nella cache UIImages proprio come fa -imageNamed:. Li carica e li trattiene. Puoi tenerli anche tu, usando un NSDictionary e implementare il tuo -imageNamed:

Ma io sono più preoccupato per il problema che stai avendo con il ridimensionamento. Come vengono importate le tue immagini in Documenti, come le ridimensiona e hai testato lo stesso file immagine memorizzato nel pacchetto? Dubito che lo -imageNamed: abbia qualcosa a che fare con questo. Sospetto più cose come il fatto che al bundle sia applicata una certa compressione (anche se non ho ancora una teoria sul perché questo sarebbe importante nella pratica), differenze nel file o differenze nel modo in cui il resto del programma si sta comportando durante il ridimensionamento (causando conflitti sul disco o sulla CPU). Il caching è improbabile in relazione a questo problema.

Farei un po 'di profiling con gli strumenti per cercare di scoprire da dove proviene il choppiness. Stai esaurendo il disco, la CPU, la memoria? Qual è il collo di bottiglia?

+0

hmmm ... interessante .. Controllerò ora e tornerò da te. Grazie – RexOnRoids

+0

Ho risolto il problema ma non so ancora quale fosse la causa esatta. Le immagini che scalavano senza problemi erano di 4 kb, avevano anche dimensioni (potenza di 2) e erano file PNG generici mentre le immagini che scalavano in modo choppily avevano dimensioni di 200 kb +, dimensioni non uniformi ed erano file PNG di tipo Adobe Fireworks. Una volta ridimensionate le dimensioni del file, livellato le dimensioni, cambiato il tipo di file, tutto iniziò a scalare senza intoppi ... Chissà perché;) – RexOnRoids

1

Che ne dici di scrivere la cache delle immagini? Hai tutti i pezzi sul posto, ora hai solo bisogno di incapsularlo e tenere un registro delle immagini che hai già caricato.

8

Il modo più semplice sarebbe un NSMutableDictionary memorizzare le immagini memorizzate nella cache e un metodo di cache chiaro:

@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 

Nota: si dovrebbe chiamare +[UIImage clearCache] dal tuo metodo didReceiveMemoryWarning. Inoltre, clearCache invaliderà tutti gli oggetti nella cache, non solo gli oggetti non utilizzati; una sottoclasse UIImage e un meccanismo di memorizzazione nella cache più complicato sarebbero necessari per porvi rimedio.

+0

Soluzione semplice e di qualità. +1 – iPadDeveloper2011

+0

Sicuramente, grazie. +1 –

9

Ho effettuato un'estensione della risposta fornita da rpetrich e ho annullato il metodo imageName: metodo per aggiungere più di una sostituzione. Cerca prima il pacchetto principale e poi cerca nella directory delle cache. Ovviamente è possibile cambiare la directory delle cache nella directory dei documenti.

@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

Fantastico! Mettendo questo a buon uso. :) –

+1

Non dovresti sovrascrivere i metodi in una categoria. Basta usare un nome diverso. Vedi qui: http://stackoverflow.com/a/5272612/921573 –

+0

Inoltre, consiglierei di usare 'NSCache' invece di' NSMutableDictionary'. È lì solo per quello. –

Problemi correlati