简体   繁体   English

在tableView(_:cellForRowAt :)内部下载图像导致单元格不停闪烁

[英]download image inside tableView(_:cellForRowAt:) causing cells non-stop flashing

i want the image downloaded lazily for each UITableViewCell on the method tableView(_:cellForRowAt:) . 我想为tableView(_:cellForRowAt:)方法上的每个UITableViewCell延迟下载图像。 when the table view shows on the screen, it non-stops flashing on each cell and i can't scroll the tableView. 当表格视图显示在屏幕上时,它在每个单元格上不停闪烁,并且我无法滚动tableView。

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "MessageCell", for: indexPath) as! MessageCell
    let row = indexPath.row

    cell.content.delegate = self
    cell.content.text = messages[row].content
    cell.date.text = messages[row].createdDateStrInLocal
    cell.messageOwner.text = messages[row].user

    self.fetchUserAvatar(avatarName: messages[row].user, handler: ({ img in
        cell.profileImageView.image = img
        tableView.reloadRows(at: [indexPath], with: .automatic)
    }))
    return cell
}

fileprivate func fetchUserAvatar(avatarName: String, handler: @escaping (UIImage) -> 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, completionHandler: { data, response, error in
            guard error == nil else {
                print(error!)
                return
            }
            if let httpResponse = response as? HTTPURLResponse, 200...299 ~= httpResponse.statusCode, let data = data, let urlStr = String(data: data, encoding: String.Encoding.utf8), urlStr != "NULL", urlStr.contains("http"), let url = URL(string: urlStr) {
                self.defaultSession.dataTask(with: url, completionHandler:{ data, respone, error in
                    guard error == nil else {
                        print(error!)
                        return
                    }
                    DispatchQueue.main.async {
                        if let httpResponse = response as? HTTPURLResponse, 200...299 ~= httpResponse.statusCode, let data = data, let img = UIImage(data: data) {
                            self.cacheImage.setObject(img, forKey: avatarName as NSString)
                            handler(img)
                        }
                    }
                }).resume()
            }
        }).resume()
}

Despite the fact the this is not a safe way to download image to cell, you need to remove tableView.reloadRows(at: [indexPath], with: .automatic) . 尽管事实上这不是将图像下载到单元格的安全方法,但是您需要删除tableView.reloadRows(at: [indexPath], with: .automatic) This cause infinite loop. 这会导致无限循环。

And make sure you update constraint when image is updated. 并确保在更新图像时更新约束。

For fetchUserAvatar make it in separate Background thread. 对于fetchUserAvatar其放在单独的背景线程中。 In the completion block, get back to main thread and update table cell thumb image. 在完成块中,返回到主线程并更新表单元缩略图。 Never reload table view inside `cellForRowAt indexPath: IndexPath.' 切勿在cellForRowAt indexPath:IndexPath中重新加载表视图。 Because it is already reloading cells. 因为它已经在重新加载单元格。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM