swift - 我应该怎么做才能在 tableView 中加载异步图像?
问题描述
好吧,我应该在表格视图中加载图像,我下载并加载成功,但是当我尝试在表格视图中显示时,它们没有出现,但是,如果我在表格视图中滚动,图像会出现但是图像不会在单元格的中间。
我正在使用 swift 4.2
这行帮助我下载并加载了图像
extension UIImageView {
func downloaded(from url: URL, contentMode mode: UIView.ContentMode = .scaleAspectFit) {
contentMode = mode
URLSession.shared.dataTask(with: url) { data, response, error in
guard
let httpURLResponse = response as? HTTPURLResponse, httpURLResponse.statusCode == 200,
let mimeType = response?.mimeType, mimeType.hasPrefix("image"),
let data = data, error == nil,
let image = UIImage(data: data)
else { return }
DispatchQueue.main.async() {
self.image = self.resizedImageWith(image: image, targetSize: CGSize(width: 100.0, height: 50.0))
}
}.resume()
}
func downloaded(from link: String, contentMode mode: UIView.ContentMode = .scaleAspectFit) {
guard let url = URL(string: link) else { return }
downloaded(from: url, contentMode: mode)
}
}
在我的表格视图控制器中,我使用此功能下载图像
func loadImages()
{
for img in arrFavServices
{
if let url = img?.logo
{
let imgDownload = UIImageView()
imgDownload.downloaded(from: url, contentMode: .redraw)
arrImages.append(imgDownload)
}
else
{
let imgDownload = UIImageView()
imgDownload.image = UIImage(named: "logo")
arrImages.append(imgDownload)
}
tableView.reloadData()
tableView.layoutIfNeeded()
tableView.layoutSubviews()
utilActivityIndicator.shared.hideLoader(view: view)
}
}
数组 arrFavServices 包含所有图像的 url,而 arrImages 包含之前下载的所有图像。在 viewdidload 中调用了函数 loadImages。我使用这个功能来显示图像
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
if (arrFavServices[indexPath.section]?.logo) != nil
{
if arrImages[indexPath.section].image != nil
{
cell.imageView?.image = arrImages[indexPath.section].image
cell.imageView?.contentMode = .center
}
}
// Configure the cell...
if let color = arrFavServices[indexPath.section]?.color
{
cell.backgroundColor = UIColor(hexString: color)
}
return cell
}
我的错误是什么?请帮帮我
解决方案
我认为你有两个选择
当单元格可见时,您会异步下载图像(我推荐)
下载所有图像并显示单元格可见
如果您下载所有图像会增加应用程序的内存使用量,如果使用过多,iOS 将使您的应用程序崩溃。
第一条路径:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
if let logo = arrFavServices[indexPath.section]?.logo {
// We need download image here
cell.imageView?.downloaded(from: logo, contentMode: .center)
}
// Configure the cell...
if let color = arrFavServices[indexPath.section]?.color {
cell.backgroundColor = UIColor(hexString: color)
}
return cell
}
第二条路径:
您可以使用调度组。UITableView 正在等待下载所有图像。
// Cache array
var downloadedImages: [UIImage] = []
// Create an instance
var dispatchGroup = DispatchGroup()
func loadImages() {
// Every tick of loop, we enter the group
for img in arrFavServices {
// Join the group
dispatchGroup.enter()
if let url = img?.logo {
let imgDownload = UIImageView()
imgDownload.downloaded(from: url, contentMode: .redraw, completion: { [weak self] downloadedImage in
guard let self = self else { return }
self.downloadedImages.append(downloadedImage)
// And leave group when task is done
dispatchGroup.leave()
})
} else {
let imgDownload = UIImageView()
imgDownload.image = UIImage(named: "logo")
arrImages.append(imgDownload)
// We can leave here too because we add image to array
dispatchGroup.leave()
}
}
// We have to listen group, and that we update tableView or UI todo
dispatchGroup.notify(queue: .main) {
self.tableView.reloadData()
self.tableView.layoutIfNeeded()
self.tableView.layoutSubviews()
self.utilActivityIndicator.shared.hideLoader(view: self.view)
}
}
您可以设置完成处理程序,如下所示
extension UIImageView {
func downloaded(from url: URL, contentMode mode: UIView.ContentMode = .scaleAspectFit, completion: ((UIImage) -> Void)?) {
contentMode = mode
URLSession.shared.dataTask(with: url) { data, response, error in
guard
let httpURLResponse = response as? HTTPURLResponse, httpURLResponse.statusCode == 200,
let mimeType = response?.mimeType, mimeType.hasPrefix("image"),
let data = data, error == nil,
let image = UIImage(data: data)
else { return }
DispatchQueue.main.async() {
completion?(image)
}
}.resume()
}
func downloaded(from link: String, contentMode mode: UIView.ContentMode = .scaleAspectFit, completion: ((UIImage) -> Void)?) {
guard let url = URL(string: link) else { return }
downloaded(from: url, contentMode: mode, completion: completion)
}
}
推荐阅读
- c++ - 未定义的参考在 arm chromebook 上编译 taskwarrior
- json - 在Angular中使用httpclient服务加载本地json异步
- javascript - 在 VueJS 中将组件作为道具传递时出现未知的自定义元素错误
- angular - 构建后如何使用href修复离子路由?
- c++ - 输出混乱
- javascript - 悬停在带有 textarea 的 div 元素上不起作用
- python - 属性错误:Python
- python - 在查找/更新值时,为什么 Python dict 比 set 更有效?
- javascript - 如何使用来自 API 的数据填充选择下拉元素 - ReactJS
- ffi - 带有标记值的安全 API