从Tableview单元格的URL下载图片时出现问题

pxyaymoc  于 2022-09-19  发布在  Swift
关注(0)|答案(1)|浏览(868)

我从URL下载我的表格视图单元格的图片时遇到了很多问题。我尝试了同步和异步下载,但都不起作用。

对于同步下载,Xcode会给我紫色警告,图片不会显示在我的表视图中。

警告:

“...的同步URL加载不应在此应用程序的主线程上发生,因为这可能会导致用户界面无响应。请切换到异步网络API,如URLSession。”

对于异步下载,下载后的代码立即执行,下载无法完成,结果为空。

我该怎么办?

我的代码是:

(我是分批加载Tableview,15个帖子,这是分批加载代码)

func reloadBatch(){
    for i in currentRow...currentRow+15{
        if i == posts.count{
            return
        }

        let post = posts[i] // documens

        if post.posttype == 1{
            let uP = UIImage(url: URL(string: post.userphoto!)) ?? UIImage(named: "Jordan")
            postCell.append(LoadedCellModel(posttype: 1, sender: post.sender, userphoto: uP, title: post.title, photo: nil, videoURL: nil, content: post.content))
        }else if post.posttype == 2{
            let uP = UIImage(url: URL(string: post.userphoto!)) ?? UIImage(named: "Jordan")
            let pic = UIImage(url: URL(string: post.photo![0])) ?? UIImage(named: "Jordan")
// This is the picture that does not show up, "photo" is an array of pictures' URL(in string)

            postCell.append(LoadedCellModel(posttype: 2, sender: post.sender, userphoto: uP, title: post.title, photo: pic, videoURL: nil, content: post.content))
            print(pic)
        }
    }

    currentRow += 15
    DispatchQueue.main.async {
        self.tableView.reloadData()
    }
}

extension UIImage {
  convenience init?(url: URL?) {
    guard let url = url else { return nil }

    do {
      self.init(data: try Data(contentsOf: url))
    } catch {
      print("Cannot load image from url: (url) with error: (error)")
      return nil
    }
  }
}
a2mppw5e

a2mppw5e1#

从网上获取图像等数据是异步的。也就是说,这需要时间来做。所以你需要“等待”,直到数据可用后才能使用。注意警告消息...Please switch to an asynchronous networking API such as URLSession

有很多方法可以做到这一点。在这里,我介绍了一种简单的方法,即使用带有completion handler的函数。

这意味着,您不能像在let uP = UIImage(url: URL(string: post.userphoto!)) ?? UIImage(named: "Jordan")中那样使用此函数(getImage(url: ..)

您必须使用闭包:

getImage(url: url) { img in
     // do something with img
 }

以下是下载一张图片的示例代码:

struct ContentView: View {
    @State var uimg: UIImage?
    let token = "xxxx" // <-- your secret token

    var body: some View {
        VStack {
            if uimg == nil {
                Text("downloading")
                ProgressView()
            } else {
                Image(uiImage: uimg!).resizable().frame(width: 333, height: 333)
            }
        }
        .onAppear {
            guard let url = URL(string: "https://firebasestorage.googleapis.com/v0/b/pirateforum-f2f04.appspot.com/o/images%2F1663116366.2403781.png?alt=media&token=(token)") else { return }
            getImage(url: url) { img in
                self.uimg = img
            }
        }
    }

    func getImage(url: URL, completion: @escaping (UIImage?) -> Void) {
        URLSession.shared.dataTask(with: url) { data, response, error in
            if let data = data, let img = UIImage(data: data) {
                completion(img)
            } else {
                completion(nil)
            }
        }.resume()
    }
}

附注:如果警告消息中没有显示您的秘密令牌,请将其移除。

相关问题