2016-09-24 4 views
0
if let toID = message.chatPartnerId() { 
     firebaseReference.child(toID).observeSingleEvent(of: .value, with: { (snapshot) in 
      if let dictionary = snapshot.value as? [String: Any] { 


      cell.nameLabel.text = dictionary["displayname"] as? String 
      let pic = dictionary["pictureURL"] as! String 
       print("THIS IS THE URL FOR EACH DISPLAYNAME") 
       print(dictionary["displayname"] as? String) 
       print(pic) 


       if let imageFromCache = MainPageVC.imageCache.object(forKey: pic as NSString) { 

        cell.pictureLabel.image = imageFromCache 
       } else { 

        let requested = URLRequest(url: URL(string: pic)!) 

        URLSession.shared.dataTask(with: requested) {data, response, err in 


         if err != nil { 
          print(err) 
         } else { 

           DispatchQueue.main.async { 

           let imageToCache = UIImage(data: data!) 
         MainPageVC.imageCache.setObject(imageToCache!, forKey: pic as NSString) 
           //cell.pictureLabel.image = nil 
           cell.pictureLabel.image = imageToCache 

          } 
         } 

         }.resume() 
       } 
      } 
     }) 
    } 


    return cell 
} 

Ich habe diesen Code in meinem cellForRowAtIndexPath und ich bekomme eine Tonne wirklich schlechtes Verhalten. Ich bekomme auch ähnliches Verhalten auf anderen Seiten, aber aus irgendeinem Grund gibt dieser Codeblock mit ungefähr 90% Konsistenz falsche Informationen für Zellen zurück.Bilder laden falsch mit Cache

Ich bekomme viele doppelte Bilder verwendet, displaynames an den falschen Stellen, aber wenn ich tatsächlich in eine Person klicke, zeigt meine Detailseite jedes Mal die richtigen Informationen. Dieser Code ist der typische didSelectRowAtIndexPath und die Person übergeben.

Was ich nicht verstehe ist, warum auf der ersten Belastung dieser Seite alle Informationen vermasselt sind, aber wenn ich jemanden anklicke und zurückkomme, hat der ganze tableview korrekte Namen und Bilder. Die Namen/Bilder reparieren auch, wenn ich eine Zelle vom Bildschirm scrollen und dann zurückkommen.

Ich bekomme dieses Verhalten überall in meiner App, mittlerweile sehe ich Caching/Laden überall so gemacht. Ist es, weil ich den Code in meinem cellForRowAtIndexPath laufen lasse? Der einzige Unterschied, den ich sehe, ist, dass ich es dort ausführe, anstatt eine Funktion innerhalb meiner Person-Klasse zu erstellen, die Zellen konfiguriert und so ausführt. Was ich nicht verstehe, ist, warum das einen Unterschied machen würde, denn soweit ich weiß, wäre das Ausführen einer Funktion innerhalb von cellforRowAtIndexpath dasselbe wie das Kopieren desselben Codes in dieselbe?

Irgendwelche Ideen/Vorschläge?

Edit: Ich bin immer eine sehr ähnliche Situation, wenn ich den folgenden Code renne:

self.PersonalSearchesList = self.PersonalSearchesList.sorted{ $0.users > $1.users } 

self.tableView.reloadData() 

Wo ich meine Array bin Sortierung vor meinen Daten neu zu laden. Die Informationen werden manchmal zuerst falsch geladen, aber sobald ich die Zelle vom Bildschirm scrolle, komme ich zurück zu ihr, sie korrigiert sich immer selbst.

+0

Löschen Sie das Zellbild in Vorbereitung für die Wiederverwendung, versuchen Sie auch, das Bild in willDisplayCell zu setzen. –

+0

Ich hatte PrepareForReuse vorher noch nicht gesehen, also habe ich einen Test "Dies wird aufgerufen" gemacht und das Bild auf Null gesetzt. Ich habe das Bild noch nicht in WillDisplayCell eingestellt, aber mein Array ist 6 Leute lang, aber ich bekomme das "Dies wird aufgerufen" ungefähr 20 Mal in der Konsole ausgedruckt. Wenn mein Array 6 Personen lang ist, sollte das nur 6 mal ja heißen? Vielleicht ist das ein Hinweis darauf, was vor sich geht. Ich ziehe aber vom firebase, also macht das vielleicht Sinn, wie es für das Einzelteil 1 genannt werden würde. Dann für Einzelteil 1 und 2 und dann für 1 2 und 3 und so weiter. – user6820041

+0

Ja, ich bekomme immer noch das gleiche Problem mit diesen Vorschlägen leider. – user6820041

Antwort

1

, wenn Sie mit schnellen 3 hier einigen praktischen Funktionen, die es Ihnen ermöglichen, ein Bild zu Ihrem Anwendungsverzeichnis von einer URL zu speichern und sie dann in der App von überall zugreifen:

func saveCurrentUserImage(toDirectory urlString:String?) { 
    if urlString != nil { 
     let imgURL: URL = URL(string: urlString!)! 
     let request: URLRequest = URLRequest(url: imgURL) 

     let session = URLSession.shared 
     let task = session.dataTask(with: request, completionHandler: { 
      (data, response, error) -> Void in 

      if (error == nil && data != nil) { 
       func display_image() { 
        let userImage = UIImage(data: data!) 

        if let userImageData = UIImagePNGRepresentation(userImage!) { 
         let filename = self.getDocumentsDirectory().appendingPathComponent("userImage") 
         try? userImageData.write(to: URL(fileURLWithPath: filename), options: [.atomic]) 
        } 
       } 
       DispatchQueue.main.async(execute: display_image) 
      } 
     }) 
     task.resume() 
    } 
} 

und dann zugreifen mit jeder view-Controller mit diesem:

extension UIViewController { 

    func getImage(withName name: String) -> UIImage { 
     let readPath = getDocumentsDirectory().appendingPathComponent(name) 
     let image = UIImage(contentsOfFile: readPath) 
     return image! 

    } 
} 

und schließlich es so nennen:

cell.pictureLabel.image = getImage(withName: "userImage") 

Wenn Sie die Funktion vor dem Ausführen von cellForRowAtIndexPath ausführen können, können Sie vor dem Download überprüfen, ob das Foto nicht im Verzeichnis ist. Wenn die Seite anfänglich geladen wird, treten möglicherweise seltsame Verhaltensweisen auf, da mehrere Netzwerkanrufe gleichzeitig ausgeführt werden. Ich würde nicht empfehlen, irgendwelche Netzwerkanrufe in cellForRowAtIndexPath zu machen, weil jedes Mal, wenn die Zellen neu initialisiert werden, es diesen Netzwerkanruf für jede Zelle machen wird.

Hoffe es hilft!

EDIT: Diese Methode zum Speichern und Abrufen von Bildern ist für Bilder, die Sie beibehalten möchten. Wenn Sie sie aus dem Speicher löschen möchten, müssen Sie sie aus Ihrem Verzeichnis löschen.