在为UITableView Cell缓存图像时我做错了什么

时间:2019-06-09 21:15:31

标签: ios swift uitableview

基本上,我正在构建一个应用程序,该应用程序将使用来自其余API的数据。 在数据中还存在一对作为URL下载的图像。因此,尽管最好只下载这些图像一次,然后再将其缓存以在UITableView Cells上重复使用,以此类推。 如何正确使用此功能?

所以让我们开始吧。首先,我创建了以下类来处理下载/缓存图像:

class ImageService {

    static let cache = NSCache<NSString, UIImage>()

    static func downloadImage(url:URL, completion: @escaping (_ image:UIImage?)->()) {

        let dataTask = URLSession.shared.dataTask(with: url) { (data, response, error) in
            var downloadedImage:UIImage?

            if let data = data {

                downloadedImage = UIImage(data: data)
            }

            if downloadedImage != nil {
                self.cache.setObject(downloadedImage!, forKey: url.absoluteString as NSString)
            }

            DispatchQueue.main.async {
                completion(downloadedImage)
            }

        }
        dataTask.resume()

    }

    static func getImage(url:URL, completion:@escaping (_ image:UIImage?)->()) {

        if let image = self.cache.object(forKey: url.absoluteString as NSString) {
            completion(image)
        } else {
            downloadImage(url: url, completion: completion)
        }

    }

}

在上面的代码中,我刚刚在我的UITableView类中调用了

class TableViewController: UITableViewController {

    private var articlesViewModel:ArticleViewModel?


    override func viewDidLoad() {
        super.viewDidLoad()

        self.tableView.showsVerticalScrollIndicator = false
        self.navigationController?.navigationBar.prefersLargeTitles = true

        //Call Network
        Networking.getApiData(url: Networking.urlRequest) { [weak self] (articles) in

            //Data from API
            self?.articlesViewModel = ArticleViewModel(modelRef: articles)

            DispatchQueue.main.async {
                self?.tableView.reloadData()
            }
        }
    }


    //MARK: TableView DataSource
    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1 //Static
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.articlesViewModel?.updateTableCount() ?? 1
    }


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

        if let title = self.articlesViewModel?.updateTableTitleForIndex(indexpath: indexPath.row) {
            cell.titleCell.text = title
        }
        if let description = self.articlesViewModel?.updateTableDescriptionForIndex(indexpath: indexPath.row) {
            cell.descriptionCell.text = description
        }
        if let pictureURL = self.articlesViewModel?.updateTableImageForIndex(indexpath: indexPath.row) {
            ImageService.getImage(url: URL(string: pictureURL)!) { (finalImage) in
                cell.imageCell.image = finalImage
            }
        }


        return cell
    }



}

但是,运行应用程序后,我得到了以下结果: 似乎所有缓存的图像都在我从 ViewDidLoad

上的API获得结果之前出现

enter image description here

如果我向下滚动然后再次向上滚动,则会得到以下结果: 似乎一切都“重新排序”了,那么一切看起来还不错。

enter image description here

其他类别:

ViewModel:

class ArticleViewModel {

    static var articlesRef:[Article]!

    init(modelRef:[Article]) {
        ArticleViewModel.articlesRef = modelRef
    }


    //MARK: Functions
     func updateTableCount() -> Int {
        return ArticleViewModel.self.articlesRef.count
    }

     func updateTableTitleForIndex(indexpath:Int) -> String {
        return ArticleViewModel.self.articlesRef[indexpath].title ?? ""
    }

    func updateTableDescriptionForIndex(indexpath:Int) -> String {
        return ArticleViewModel.self.articlesRef[indexpath].description ?? ""
    }

    func updateTableImageForIndex(indexpath:Int) -> String {
        return ArticleViewModel.self.articlesRef[indexpath].urlToImage ?? ""
    }

}

网络层:

class Networking {

    static var urlRequest = "https://newsapi.org/v2/everything?q=apple&from=2019-06-05&to=2019-06-05&sortBy=popularity&apiKey=04d5f33acdde48f1a22a90f46fc483b5"


    static func getApiData(url: String?, _ completion:@escaping([Article]) -> ()) {

        guard let unrwpUrl = url else {return}

        let request = URL(string: unrwpUrl)

        URLSession.shared.dataTask(with: request!) { (data, request, error) in

            if let data = data {

                do {
                    let decodedData = try JSONDecoder().decode(Articles.self, from: data)


                    completion(decodedData.articles)

                }catch{
                    print(error.localizedDescription)
                }
            }


            }.resume()
    }
}

型号:

struct Articles: Decodable {
    let articles:[Article]
}

struct Article: Decodable {
    let title:String?
    let author:String?
    let description:String?
    let urlToImage:String?
}

0 个答案:

没有答案