2015-12-02 14 views
9

senza che sto usando AlamofireImage per impostare un'immagine su un UIImageView in un UITableViewCell in questo modo:AlamofireImage af_setImageWithURL in un UITableViewCell un'immagine segnaposto

cell.imageView.af_setImageWithURL(url)

L'immagine non mostra dopo il download. Mostrerà l'immagine la seconda volta quando viene caricata dalla memoria cache.

Sembra che l'uso di un'immagine segnaposto faccia la differenza.

questo funziona e stampa l'indirizzo dell'immagine (scaricati):

cell.imageView.af_setImageWithURL(URL, placeholderImage: UIImage(named: "placeholder"), filter: nil, imageTransition: .None, completion: { (response) -> Void in 
        print("image: \(cell.imageView.image)") 
       }) 

Questo non funziona e stampe "immagine: nil"

cell.imageView.af_setImageWithURL(URL, placeholderImage: nil, filter: nil, imageTransition: .None, completion: { (response) -> Void in 
        print("image: \(self.image)") 
       }) 

Funziona anche quando si impostano le cellule ImageView a un'immagine vuota prima di fare af_setImageWithURL:

cell.imageView.image = UIImage()

Si tratta di un bug in UITableViewCell, AlamofireImage o sto facendo qualcosa di sbagliato?

+0

Sembra che le dimensioni di cell.imageView corrispondano di conseguenza, a seconda che esista o meno un'immagine. Se non c'è immagine, riduce la sua cornice per non occupare spazio. Quindi, quando non usi un segnaposto, pensa che non ci sia immagine, quindi si ritira. Quindi, quando l'immagine arriva in modo asincrono, la cornice è già ridotta, quindi da nessuna parte per mettere l'immagine. – Harris

risposta

1

È possibile stampare l'errore aggiungendo 2 righe di codice in modo da ottenere più idee sul problema.

cell.imageView.af_setImageWithURL(URL, placeholderImage: UIImage(named: "placeholder"), filter: nil, imageTransition: .None, completion: { (response) -> Void in 
        print("image: \(cell.imageView.image)") 
        print(response.result.value) //# UIImage 
        print(response.result.error) //# NSError 

       }) 

Nel mio caso si è verificato un problema con l'URL dell'immagine. Stava scaricando l'immagine quando la apro nel browser.

1

Questa domanda ha un paio di anni, ma forse questa risposta può essere utile a qualcun altro con un problema simile, come me prima di trovare la soluzione giusta.

Poiché le immagini vengono caricate in modo asincrono, se non abbiamo fornito un'altezza fissa per UIIMageView , dobbiamo forzare l'aggiornamento di una cella al termine del download. Questo perché l'aggiornamento della cella (ad esempio il ricalcolo dei vincoli di AutoLayout) viene eseguito automaticamente solo dopo il metodo cellForRowAt, che viene chiamato quando una cella viene visualizzata per la prima volta o quando si scorre la tabella per mostrare altre celle. In entrambi i casi, probabilmente le immagini non sono ancora state scaricate dal metodo af_setImage(), quindi non verrà visualizzato nulla tranne il segnaposto poiché le loro dimensioni sono sconosciute per il momento.

Per forzare l'aggiornamento di una cella, è necessario utilizzare i metodi beginUpdates() e endUpdates(), inserendoli all'interno del gestore di completamento di .af_setImage(). In questo modo, ogni volta che il download è completato, la cella verrà aggiornata.

Ma, per evitare un loop, prima di chiamare beginUpdates()/endUpdates() dobbiamo controllare se abbiamo già aggiornare la cella prima, perché chiamando questi metodi, il metodo cellForRowAt viene chiamato nuovamente e conseguentemente la af_setImage() e la sua chiusura di completamento con beginUpdates()/endUpdates() al suo interno).

Ciò significa che dobbiamo aggiornare la cella solo quando il download è appena finito, e non quando l'immagine è già incassata (perché, se è incassata, significa che abbiamo già aggiornato la cella).Questo può essere ottenuto controllando la risposta del gestore di completamento: se non è nil, l'immagine è stata appena scartata, se è nil, l'immagine è stata incassata.

Come un lato beneficio l'altezza della cella saranno automagicamente regolato (ricordarsi di mettere tableView.estimatedRowHeight = 400 e tableView.rowHeight = UITableViewAutomaticDimension nel metodo viewDidLoad())

Infine, qui è il codice:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
     // Dequeue your cell 
     let cell = self.tableView.dequeueReusableCell(withIdentifier: "YourCustomCellIdentifier") as! YourCustomTableViewCell 

     // get picture url from the data array 
     let pictureUrl = self.yourCellsData[indexPath.row].pictureUrl 

     // async download 
     cell.pictureView.af_setImage(
       withURL: URL(string: pictureUrl)!, 
       placeholderImage: UIImage(named: "YourPlaceholder.png"), 
       filter: nil, 
       imageTransition: UIImageView.ImageTransition.crossDissolve(0.5), 
       runImageTransitionIfCached: false) { 
        // Completion closure 
        response in 
         // Check if the image isn't already cached 
         if response.response != nil { 
          // Force the cell update 
          self.tableView.beginUpdates() 
          self.tableView.endUpdates() 
         } 
       } 

     return cell 
     } 

Questo è tutto! ;-)

+0

Ciao Guido, questo codice funziona molto bene! Sfortunatamente ha un grosso problema: quando si scorre, la tabella viene ridisegnata e scorre su e giù, è un'esperienza da letto per gli utenti. Sta succedendo solo a me? –

+0

Ciao Francesco, non ricordo di aver avuto un problema simile, puoi pubblicare un progetto di esempio che mostri questo problema? – Guido

+0

Ciao Guido, ho risolto il problema valutando l'altezza della cella corretta e creando nuove celle con valori fissi. Non ho più il codice rotto, mi dispiace. Proverò a riprodurre, se troverò un modo per avere pragmaticamente il problema che posterò di nuovo qui. Grazie! –