Lorsque je fais une transition vers un viewController avec un tableView, la cellule de tableView envoie immédiatement une requête au serveur en utilisant la méthode fetchUserAvatar(avatarName: handler: (String) -> Void)
. Cette méthode renvoie une URL qui lie à l'image. Téléchargez-la et mettez en cache l'image cacheImage
est un objet de NSCache
. Cet objet cacheImage
a été initialisé dans le viewController précédent et attribué du précédent à ce viewController à l'aide de prepare(for segue: UIStoryboardSegue, sender: Any?)
. Lorsque ce viewController s'affiche, je ne peux pas voir l'image dans la cellule. Mais si je ferme le viewController et fais une transition à nouveau vers ce viewController avec tableView, l'image s'affichera. Je pense (je suppose) que c'est parce que les images n'ont pas encore été toutes entièrement téléchargées. Donc, je ne peux pas voir les images. Mais si je ferme le viewController et charge un objet du viewController et que le viewController obtient les images depuis le cache. Par conséquent, les images pourraient être affichées.
Je veux savoir comment éviter ce problème ? Merci.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "MessageCell", for: indexPath) as! MessageCell
let row = indexPath.row
cell.content.text = messages[row].content
cell.date.text = messages[row].createdDateStrInLocal
cell.messageOwner.text = messages[row].user
if let avatar = cacheImage.object(forKey: messages[row].user as NSString){
cell.profileImageView.image = avatar
} else {
fetchUserAvatar(avatarName: messages[row].user, handler: { [unowned self] urlStr in
if let url = URL(string: urlStr), let data = try? Data(contentsOf: url), let avatar = UIImage(data: data){
self.cacheImage.setObject(avatar, forKey: self.messages[row].user as NSString)
cell.profileImageView.image = avatar
}
})
}
return cell
}
fileprivate func fetchUserAvatar(avatarName: String, handler: @escaping (String) -> Void){
guard !avatarName.isEmpty, let user = self.user, !user.isEmpty else { return }
let url = URL(string: self.url + "/userAvatarURL")
var request = URLRequest(url: url!)
let body = "username=" + user + "&avatarName=" + avatarName
request.httpMethod = "POST"
request.setValue("application/x-www-form-urlencoded; charset=utf-8", forHTTPHeaderField: "Content-Type")
request.httpBody = body.data(using: .utf8)
defaultSession.dataTask(with: request as URLRequest){ data, response, error in
DispatchQueue.main.async {
if let httpResponse = response as? HTTPURLResponse {
if 200...299 ~= httpResponse.statusCode {
print("statusCode: \(httpResponse.statusCode)")
if let urlStr = String(data: data!, encoding: String.Encoding.utf8), urlStr != "NULL" {
handler(urlStr)
}
} else {
print("statusCode: \(httpResponse.statusCode)")
if let unwrappedData = String(data: data!, encoding: String.Encoding.utf8) {
print("POST: \(unwrappedData)")
self.warning(title: "Fail", message: unwrappedData, buttonTitle: "OK", style: .default)
} else {
self.warning(title: "Fail", message: "unknown error.", buttonTitle: "OK", style: .default)
}
}
} else if let error = error {
print("Error: \(error)")
}
}
}.resume()
}
Je l'ai modifié, et déplacé le code de téléchargement dans viewdidload et rechargé le tableView, le résultat est le même.