即使使用缓存

时间:2016-09-24 01:45:33

标签: 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()

我在重新加载数据之前对数组进行排序。信息有时首先加载不正确,但是一旦我将屏幕上的单元格滚动出来然后再回到它,它总是会自行纠正。

1 个答案:

答案 0 :(得分:1)

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

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()
    }
}

然后使用以下任意视图控制器访问它:

 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")

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

希望它有所帮助!

  

编辑:这种图像保存和检索方法适用于您想要保留的图像。如果你想从内存中删除它们,你必须从目录中删除它们。