2010-06-28 5 views
8

Fino a iOS 3.2, ho usato questo tipo di codice per caricare un'immagine UIImageView in background, e ha funzionato bene ...iOS4 e sfondo [UIImage setImage:]

Codice:

- (void)decodeImageName:(NSString *)name 
{ 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
    UIImage *newImage = [UIImage imageNamed:name]; 
    [myImageView setImage:newImage]; 
    [pool release]; 
} 
... 
[self performSelectorInBackground:@selector(decodeImageName:) withObject:@"ID"] 

. .. anche se [UIImageView setImage:] non era thread-safe!

Ma da iOS 4, non funziona più ... Le immagini vengono visualizzate sullo schermo due secondi dopo la chiamata setImage. E se faccio un [myImageView performSelectorOnMainThread:@selector(setImage:) withObject:newImage waitUntilDone:YES] invece di [myImageView setImage:newImage], le immagini appaiono immediatamente ma sembrano essere nuovamente decodificate al volo (ignorando il precedente [UIImage imageNamed:] che avrebbe dovuto già decodificare i dati dell'immagine), causando una pausa sul mio thread principale .. Anche se la documentazione dice La cache dell'immagine sottostante è condivisa tra tutti i thread..

Qualche idea?

+0

Ciao, grazie per avermi fatto questa domanda.Mi stavo chiedendo perché non funziona ora con la mia app. – GeneCode

risposta

3

performSelectorInBackground: esegue un selettore in un thread in background. Tuttavia setImage: è una funzione dell'interfaccia utente. Le funzioni dell'interfaccia utente dovrebbero essere eseguite solo sul thread principale. Non ho idea del particolare problema, ma questo è il primo istinto su questo codice, e potrebbe essere che iOS4 gestisca il meccanismo (non supportato) di eseguire le funzioni dell'interfaccia utente in background in qualche modo in modo diverso.

4

Non farlo in background! Non è thread-safe. Dal momento che un UIImageView è anche un NSObject, penso che l'utilizzo -[performSelectorOnMainThread:withObject:waitUntilDone:] su di esso potrebbe funzionare, come:

[myImageView performSelectorOnMainThread:@selector(setImage:) withObject:newImage waitUntilDone:NO]; 

Ed è UIImage che è stato recentemente reso thread-safe. UIImageView non è ancora thread-safe.

+1

Ciao Evadne, dove hai letto che UIImage è thread-safe? Non riesco a trovarlo da nessuna parte. – jasongregori

1

Se si utilizza iOS 4.0, si consiglia di in realtà prendere in considerazione la lettura su blocchi e GCD. Utilizzando queste tecnologie, si può semplicemente sostituire il metodo con: quote

- (void)decodeImageName:(NSString *)name 
{ 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
    UIImage *newImage = [UIImage imageNamed:name]; 

    dispatch_async(dispatch_get_main_queue(), ^{ 
     [myImageView setImage:newImage]; 
    } 

    [pool release]; 
} 
+0

Non aiuta molto. Il dispatch_async mette ancora in pausa il thread principale più a lungo di come dovrebbe essere se l'uiimage venisse nuovamente decodificato. Come posso essere sicuro che UIImage sia decodificato dopo [UIImage imageNamed: name]? –

+0

Consiglierei di supportare il sistema operativo 3.1.3 per almeno alcuni mesi e 3.2 fino a qualche mese dopo il rilascio di 4.0+ per iPad. –

1

Let:

@property(nonatomic, readonly) CGImageRef CGImage

Discussione

Se i dati dell'immagine è stata eliminata a causa della memoria i vincoli, invocando questo metodo costringe i dati a essere caricati di nuovo in memoria. Il ricaricamento dei dati dell'immagine può comportare una penalizzazione delle prestazioni.

Quindi potresti chiamare semplicemente image.CGImage. Non credo che CGImages siano pigri.

Se questo non funziona, è possibile forzare un rendering con qualcosa come

// Possibly only safe in the main thread... 
UIGraphicsBeginImageContext((CGSize){1,1}); 
[image drawInRect:(CGRect){1,1}]; 
UIGraphicsEndImageContext(); 

Alcune persone mettono in guardia thread-sicurezza. I documenti dicono che UIGraphics{Push,Pop,GetCurrent}Context() sono solo thread-main ma non menzionano nulla su UIGraphicsBeginImageContext(). Se sei preoccupato, usa CGBitmapContextCreate e CGContextDrawImage.