ios - 即使有缓存也无法正确加载图像

标签 ios swift caching

 if let toID = message.chatPartnerId() {
        firebaseReference.child(toID).observeSingleEvent(of: .value, with: { (snapshot) in
            if let dictionary = snapshot.value as? [String: Any] {


            cell.nameLabel.text = dictionary["displayname"] as? String
            let pic = dictionary["pictureURL"] as! String
                print("THIS IS THE URL FOR EACH DISPLAYNAME")
                print(dictionary["displayname"] as? String)
                print(pic)


                if let imageFromCache = MainPageVC.imageCache.object(forKey: pic as NSString) {

                    cell.pictureLabel.image = imageFromCache
                } else {

                    let requested = URLRequest(url: URL(string: pic )!)

                    URLSession.shared.dataTask(with: requested) {data, response, err in


                        if err != nil {
                            print(err)
                        } else {

                                DispatchQueue.main.async {

                                let imageToCache = UIImage(data: data!)
                      MainPageVC.imageCache.setObject(imageToCache!, forKey: pic as NSString)
                                //cell.pictureLabel.image = nil
                                cell.pictureLabel.image = imageToCache

                            }
                        }

                        }.resume()
                } 
            }
        })
    }


    return cell
}

我在我的 cellForRowAtIndexPath 中运行这段代码,我遇到了很多非常糟糕的行为。我在其他页面上也遇到了类似的行为,但出于某种原因,这段具有大约 90% 一致性的代码块返回了不正确的单元格信息。

我在错误的地方使用了很多重复的图片,displaynames,但是当我实际点击一个人时,我的详细信息页面每次都显示正确的信息。该代码是典型的 didSelectRowAtIndexPath 并传递给该人。

我不明白的是为什么在这个页面的初始加载时所有信息都搞砸了,但如果我点击某人并返回整个 tableview 具有正确的名称和图片.如果我从屏幕上滚动一个单元格然后返回到它,名称/图片也会修复。

我的应用程序中到处都是这种行为,同时我看到缓存/加载在任何地方都是这样完成的。是因为我在我的 cellForRowAtIndexPath 中运行代码吗?我看到的唯一区别是我在那里运行它,而不是在我的 Person 类中创建一个函数来配置单元格并像那样运行它。我不明白为什么这会有所不同,因为据我所知,在 cellforRowAtIndexpath 中运行一个函数与将相同的代码复制粘贴到那里是一样的吗?

有什么想法/建议吗?

编辑:当我运行以下代码时,我遇到了非常相似的情况:

self.PersonalSearchesList = self.PersonalSearchesList.sorted{ $0.users > $1.users }

self.tableView.reloadData()

在重新加载数据之前,我在哪里对数组进行排序。信息有时一开始加载不正确,但一旦我将单元格滚动到屏幕外然后返回到它,它总是会自行更正。

最佳答案

如果您使用的是 swift 3,这里有一些方便的功能,可让您从 URL 将图像保存到您的应用程序目录,然后从应用程序的任何位置访问它:

func saveCurrentUserImage(toDirectory urlString:String?) {
    if urlString != nil {
        let imgURL: URL = URL(string: urlString!)!
        let request: URLRequest = URLRequest(url: imgURL)

        let session = URLSession.shared
        let task = session.dataTask(with: request, completionHandler: {
            (data, response, error) -> Void in

            if (error == nil && data != nil) {
                func display_image() {
                    let userImage = UIImage(data: data!)

                    if let userImageData = UIImagePNGRepresentation(userImage!) {
                        let filename = self.getDocumentsDirectory().appendingPathComponent("userImage")
                        try? userImageData.write(to: URL(fileURLWithPath: filename), options: [.atomic])
                    }
                }
                DispatchQueue.main.async(execute: display_image)
            }
        })
        task.resume()
    }
}

然后使用任何 View Controller 访问它:

 extension UIViewController {

    func getImage(withName name: String) -> UIImage {
        let readPath = getDocumentsDirectory().appendingPathComponent(name)
        let image = UIImage(contentsOfFile: readPath)
        return image!

    }
}

最后这样调用它:

cell.pictureLabel.image = getImage(withName: "userImage")

如果您可以在运行 cellForRowAtIndexPath 之前运行 saveCurrentUserImage 函数,那么您可以在尝试下载之前检查目录中的照片是否为 nil。当页面最初加载时,您可能会遇到有趣的行为,因为您同时进行了多个网络调用。我不建议在 cellForRowAtIndexPath 中进行任何网络调用,因为每次重新初始化单元格时,它都会为每个单元格进行网络调用。

希望对您有所帮助!

EDIT: This method of image saving and retrieval is for images that you want to persist. If you want to erase them from memory you'll have to delete them from your directory.

关于ios - 即使有缓存也无法正确加载图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39671724/

相关文章:

ios - 如何使用 Objective-C 将特定值删除到 NSMutableArray 中?

html - jQuery Mobile 通过离线 iOS 应用程序中的文件加载数据

ios - 在 PDFView 中设置内容插入

ios - NSXMLParser:非 ASCII 字符的意外结果

Sharepoint - 如何启用无服务器访问的缓存?

performance - 如何调整 Sitecore 预取缓存

ios - Swift:将弹出窗口中的数据添加到结构中并在 TableView 中显示

iOS 错误 : [__NSArrayI objectAtIndex:]: index 1 beyond bounds [0 .。 0]

swift - GoogleSignIn 不适用于 YouTube API (Swift)

ios - 重建项目时缓存图像 url 不存在