【发布时间】:2017-05-15 16:21:57
【问题描述】:
当我使用 tableView 转到 viewController 时,tableviewcell 立即使用方法fetchUserAvatar(avatarName: handler: (String) -> Void) 向服务器发送请求。这个方法返回一个链接到图像的 url。下载并缓存图像cacheImage 是NSCache<NSString, UIImage> 的对象。这个对象cacheImage 是在之前的视图控制器中初始化的,并使用prepare(for segue: UIStoryboardSegue, sender: Any?) 从可渗透的视图控制器分配给这个视图控制器。当这个 viewController 出现时,我在单元格中看不到图像。但是我将 viewController 弹出并再次使用 tableView 转到此 viewController。图像将显示。我想(我猜)因为
图像还没有完全下载。所以,我看不到图像。但是如果我弹出 viewController 并加载 viewController 的对象,并且 viewController 从缓存中获取图像。因此,可以显示图像。
我想知道如何避免这个问题?谢谢。
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()
}
我修改了一下,把下载代码移到viewdidload里面重新加载tableview,结果还是一样。
【问题讨论】:
-
fetchUserAvatar(avatarName: handler: (String) -> Void)是主线程中的handler:闭包吗? -
我认为你需要在获取头像后重新加载单元格。我建议您查看 SDWebImage。
-
我添加了更多细节。
-
但是我应该在哪里添加重新加载?
标签: ios swift uitableview