2015-09-01 11 views
50

Come determinare la dimensione massima dell'immagine PHAsset disponibile su un dispositivo iOS, dove per "disponibile" si intende attualmente sul dispositivo, non richiede alcun download di rete dalla libreria di foto di iCloud ?Determinare la dimensione dell'immagine PHAsset più grande disponibile sul dispositivo iOS

Ho sviluppato un'app in cui una raccolta di miniature è mostrata in un UICollectionView (molto simile all'app Foto) e quindi un utente può selezionare un'immagine per vederla a schermo intero. L'immagine a dimensione intera viene scaricata da iCloud se necessario. Tuttavia, voglio mostrare all'utente la versione più grande possibile dell'immagine fino a quando non è disponibile la dimensione completa.

Il modo in cui la foto quadro funziona è piuttosto strana:

Nella vista raccolta, sto usando un PHCachingImageManager a cache (e più tardi request) le immagini con un targetSize di 186x186 pixel (il doppio dei UICollectionViewCell dimensioni a causa della ridimensionamento della retina).

Questo funziona molto bene, con uno scorrimento molto veloce e nessun ritardo nel riempimento delle celle con le immagini. Controllando la dimensione delle immagini restituite, sono tutte approssimativamente 342x256 pixel. Questo è sul mio iPhone 6 con iCloud Photo Library abilitato e 'Optimize Storage' abilitato, quindi solo piccole anteprime sono memorizzate sul dispositivo per la maggior parte delle immagini.

Tuttavia, la parte strana è che se io quindi richiedere il full size (o molto più grande) versione di qualsiasi immagine, sia con PHCachingImageManager o PHImageManager.defaultManager() utilizzando l'opzione PHImageRequestOptionsDeliveryMode.Opportunistic, la prima immagine (bassa qualità) che viene restituito è un piccolo francobollo da 60x45 pixel che sembra orribile a tutto schermo, fino a quando l'immagine a dimensione intera viene scaricata per sostituirla.

Chiaramente ci sono miniature più grandi (342x256) sul dispositivo già, come sono stati appena mostrati nella visualizzazione insieme! Allora perché diavolo non li restituisce come la prima immagine di "bassa qualità" fino a quando non è stata scaricata la dimensione completa? Per assicurarmi che le immagini 342x256 fossero già presenti sul dispositivo, ho eseguito il codice in modalità aereo, quindi nessun accesso alla rete stava accadendo.

Quello che ho trovato è che se ho richiesto qualsiasi dimensione fino a 256x256 avrei ottenuto le immagini 342x256 restituite. Non appena ho ingrandito (anche 1 pixel) mi restituirei 60x45 immagini e poi provare a scaricare l'immagine a dimensione intera.

Ho modificato il mio codice per fare prima una richiesta 256x256, seguita da una richiesta a dimensione intera con PHImageRequestOptionsDeliveryMode.HighQualityFormat (che non restituisce una piccola immagine intermedia), e che funziona magnificamente. È anche ciò che deve fare l'app Foto iOS poiché visualizza miniature di alta qualità mentre scarica l'immagine completa.

Quindi, con questo background, come faccio a sapere qual è la dimensione più grande dell'immagine del dispositivo per un PHAsset? 256x256 è un numero magico o dipende dal modo in cui iCloud Photo Library sta ottimizzando lo spazio (in base alle dimensioni della libreria e alla memoria disponibile del dispositivo)?

Certamente sembra un bug che Photos Framework non restituisca l'immagine più grande attualmente disponibile (quando viene richiesta una dimensione maggiore di quella attuale), e che per ottenere la dimensione più grande che ha, è necessario chiedere che taglia o più piccola, perché se chiedi più grande, otterrai una miniatura 60x45! Bizzarro.

UPDATE: rapporto Bug presentato ad Apple: https://openradar.appspot.com/25181601
progetto di esempio che dimostra l'errore: https://github.com/mluisbrown/PhotoKitBug

+0

Durante il recupero delle anteprime si esegue una richiesta sincrona o asincrona con PHImageManager.defaultManager()? –

+0

@ArunAmmannaya Sto usando un 'PHCachingImageManager' per ottenere le anteprime e la richiesta è asincrona. – mluisbrown

+0

Quindi si suppone di ottenere più richiamata per singola immagine con dimensioni diverse per l'immagine richiesta. Quante volte viene richiamato il callback? –

risposta

1

Usando il progetto di esempio scritto in questione sono stato in grado di riprodurre il problema nel simulatore, ma quando ho fatto la seguente modifica avrei ricevuto solo l'immagine più grande:

let targetSize = PHImageManagerMaximumSize 
+0

L'uso di 'PHImageManagerMaximumSize' per targetSize significa scaricarmi l'immagine a piena risoluzione, o nulla se non è disponibile. Sul simulatore, l'immagine a piena risoluzione è sempre disponibile. Tuttavia, su un dispositivo, le immagini a piena risoluzione di iCloud Photo Library non sono solitamente disponibili. L'uso di 'PHImageManagerMaximumSize' nel progetto di esempio non restituirà alcuna immagine perché utilizza l'opzione' networkAccessAllowed = false'. Quindi questo non serve a niente. :-( – mluisbrown

+0

@mluisbrown Tornando indietro a questo, qual è il protocollo qui? Devo cancellare questa risposta, o tenerla così che gli altri non pubblichino la stessa risposta (ovviamente quella no – markwatsonatx

+0

Mark, penso che dovresti lasciare la risposta.E 'stato un suggerimento valido.Quando l'ho visto sono tornato al mio Mac pensando "Potrebbe essere davvero così ovvio?" Vale la pena votare in effetti :) – mluisbrown

-2
[imageManager requestImageForAsset:asset 
       targetSize: PHImageManagerMaximumSize 
       contentMode:PHImageContentModeAspectFill 
       options:nil 
resultHandler:^(UIImage *result, NSDictionary *info) 
{ 
    result; 
}]; 
+1

Se ti fossi preso la briga di leggere la risposta di Mark Watson, sapresti perché questo non funziona (leggi il mio commento a quella risposta). – mluisbrown

0

In realtà non mi kn la ragione per cui Apple restituirebbe l'immagine degradata di 45 * 60 con PHImageResultIsDegradedKey = 1. Per quanto mi riguarda, ho appena chiedo l'immagine 256 * 256 con deliveryMode PHImageRequestOptionsDeliveryModeHighQualityFormat in un primo momento, poi io uso gli altri PHImageRequestOptions richiedere immagine full size come di seguito:

PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init]; 
options.networkAccessAllowed = YES; 
options.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat; 
options.progressHandler = ^(double progress, NSError *error, BOOL *stop, NSDictionary *info){ 
// code to update the iCloud download progress 
}); 

[[PHImageManager defaultManager] requestImageForAsset:asset targetSize:PHImageManagerMaximumSize contentMode:PHImageContentModeAspectFit options:options resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) { 
// code to update UIImageView or something else. 
}); 

E penso, Instagram potrebbe essere utilizzare questa soluzione simile a gestire l'immagine da iCloud.

Problemi correlati