Swift Json Tableview 滞后

Posted

技术标签:

【中文标题】Swift Json Tableview 滞后【英文标题】:Swift Json Tableview laggy 【发布时间】:2018-04-07 16:00:13 【问题描述】:

我有问题。我在 Swift 中有这段代码,但是当我在 tableview 中滚动时它非常滞后,我不知道问题是什么......?? 它下载的图像数据每个大约 20mb(我认为)..

谢谢!

func downloadJsonWithTask() 

    let url = NSURL(string: urlString)

    var downloadTask = URLRequest(url: (url as? URL)!, cachePolicy: URLRequest.CachePolicy.reloadIgnoringCacheData, timeoutInterval: 200)

    downloadTask.httpMethod = "GET"

    URLSession.shared.dataTask(with: downloadTask, completionHandler: (data, response, error) -> Void in

        let jsonData = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments)

        print(jsonData)

    ).resume()


func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! TableViewCell
    cell.nameLabel.text = nameArray[indexPath.row]
    cell.dobLabel.text = dobArray[indexPath.row]

    let imgURL = NSURL(string: imgURLArray[indexPath.row])

    if imgURL != nil 
        let data = NSData(contentsOf: (imgURL as? URL)!)
        cell.imgView.image = UIImage(data: data as! Data)
    

    return cell


///for showing next detailed screen with the downloaded info
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) 

    let vc = self.storyboard?.instantiateViewController(withIdentifier: "DetailViewController") as! DetailViewController
    vc.imageString = imgURLArray[indexPath.row]
    vc.imageString2 = imgURL2Array[indexPath.row]
    vc.imageString3 = imgURL3Array[indexPath.row]
    vc.imageString4 = imgURL4Array[indexPath.row]
    vc.imageString5 = imgURL5Array[indexPath.row]
    vc.imageString6 = imgURL6Array[indexPath.row]
    vc.nameString = nameArray[indexPath.row]
    vc.dobString = dobArray[indexPath.row]
    vc.txtString = txtArray[indexPath.row]
    vc.contactString = contactArray[indexPath.row]

    self.navigationController?.pushViewController(vc, animated: true)

【问题讨论】:

可能与每个20mb有关 旁注 - 不要在 Swift 中使用 NSURLNSData。永远,永远不要使用NSData(contentsOf:) 来加载远程数据。 @rmaddy 谢谢!我对此很陌生,但我应该改用什么? 您必须始终异步加载远程数据。通常这是通过 URLSession 完成的。但是对于带有缓存的远程表格视图图像,SDWebImage 似乎是一个流行的实用程序。 【参考方案1】:

因为这条线的问题

 let data = NSData(contentsOf: (imgURL as? URL)!)

它阻塞了主线程,你必须在其他队列中运行它,除此之外每次滚动都会重新下载图像(无缓存),所以最好使用SDWebImage

cell.imgView.sd_setImage(with: URL(string: "http://www.example.com/path/to/image.jpg"), placeholderImage: UIImage(named: "placeholder.png"))

【讨论】:

评论不用于扩展讨论;这个对话是moved to chat。【参考方案2】:

这总是会滞后的。 您在主线程中请求的图像。

尝试使用 SDWebCache 库:https://github.com/rs/SDWebImage。

1 : 会先缓存图片,避免多次 HTTP 请求。

2 : 在后台工作,因此不会影响主线程。

使用方法imageview.sd_imageFromUrl(URL(....)!)

【讨论】:

【参考方案3】:

非常清楚。您从主线程询问图像数据。每当你在主线程上执行耗时的操作时,App就会卡顿。

let data = NSData(contentsOf: (imgURL as? URL)!)

目前为止对我最有效的解决方案是使用 AlamofireImage 或 Kingfisher。这需要您了解如何将库添加到您的项目中。为了方便起见,尝试使用 Cocoapods。

我假设你可以在这里使用 Cocoapods。

如果您想要缓存支持,Kingfisher 是第一位的。缓存意味着您只需要在第一次或发生更改时向服务器发出请求。它将节省您的资源等。您需要做的就是在 ViewController 中导入 Kingfisher 模块,然后它会自动扩展 UIImageView 功能并使用 Kingfisher 扩展 kf

这里是示例代码

//ViewController.swift
import Kingfisher

// Your cellForRowAt
...
if let url = URL(string: imgURLArray[indexPath.row]) 
    cell.imgView.kf.setImage(with: url)

...

Kingfisher 将在后台执行缓存策略,以便您可以专注于应用程序。

为了放置默认图像,这对于通知用户图像非常有用,(用户希望空白白框中有一些东西 - UIImageView 而图像为零 - 在他们的屏幕中不是吗?)翠鸟帮助你和placeholder

let defaultImage = UIImage(named: "default_img")!
cell.imgView.kf.setImage(with: url, placeholder: defaultImage)

在这里Kingfisher's Github Page获取有关翠鸟的完整见解

【讨论】:

非常感谢。我之前使用过 alamofire,但后来我切换到 json 文件来存储 tableview 中的所有数据。我要测试 Kingfisher 或 AlamofireImage,因为正如你所说,我需要缓存所有图像。我会尝试然后更新你:) 很好。缓存将适用于图像等大数据。

以上是关于Swift Json Tableview 滞后的主要内容,如果未能解决你的问题,请参考以下文章

Swift,将更多数据加载到表视图中会导致滚动滞后

webView导致tableview滞后

swift tableview 将 reloadData 更改为 insertRows

Swift 3. 使用 Core Data 隐藏一个空的 tableView

如何在 Swift 2 中从 JSON 填充我的 tableView?

在swift 5中将json数据获取到tableview