在显示tableview之前尝试完成Firebase存储下载

时间:2018-03-09 21:14:55

标签: ios swift firebase firebase-storage

我有一个表格视图,根据单元格类,它将从Firebase下载图像。我注意到在使用应用程序时,具有相同单元格标识符的单元格将显示之前下载的图像,然后再显示新单元格。这是我在改变它之前所拥有的。

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    if tableData[indexPath.row]["Image"] != nil {
        let cell = tableView.dequeueReusableCell(withIdentifier: "imageNotesData", for: indexPath) as! ImageNotesCell
        cell.notes.delegate = self
        cell.notes.tag = indexPath.row
        cell.notes.text = tableData[indexPath.row]["Notes"] as! String
        guard let imageFirebasePath = tableData[indexPath.row]["Image"] else {
            return cell }
        let pathReference = Storage.storage().reference(withPath: imageFirebasePath as! String)
        pathReference.getData(maxSize: 1 * 1614 * 1614) { data, error in
            if let error = error {
                print(error)
            } else {
                let image = UIImage(data: data!)
                cell.storedImage.image = image
            }
        }
        return cell
    }
    else {
        let cell = tableView.dequeueReusableCell(withIdentifier: "notesData", for: indexPath) as! NotesCell
        //let noteString = tableData[indexPath.row]["Notes"] as! String
        cell.notes.text = tableData[indexPath.row]["Notes"] as! String
        cell.notes.delegate = self
        cell.notes.tag = indexPath.row
        return cell
    }
}

我知道这不是一个好的用户体验并且看起来很笨重,我试图将pathReference.getData移动到设置数据的位置,但在我的图像完成下载之前会出现视图。我曾尝试使用完成处理程序,但我仍然遇到问题。

override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(true)
            getSectionData(userID: userID, city: selectedCity, completion: {(sectionString) in
            self.setupTableCellView(userID: userID, city: selectedCity, section: sectionString) { (tableData) in
                DispatchQueue.main.async(execute:  {
                    self.cityName?.text = selectedCity
                    self.changeSections.setTitle(sectionString, for: .normal)
                    self.currentSectionString = sectionString
                    self.setupTableData(tableDataHolder: tableData)
                })
            }
        })
}

func setupTableCellView(userID: String, city: String, section: String, completion: @escaping ([[String:Any]]) -> () ) {
        let databaseRef = Database.database().reference().child("Users").child(userID).child("Cities").child(city).child(section)
        var indexData = [String:Any]()
        var indexDataArray = [[String:Any]]()
        databaseRef.observeSingleEvent(of: .value, with: { (snapshot) in
            for dataSet in snapshot.children {
                let snap = dataSet as! DataSnapshot
                //let k = snap.key
                let v = snap.value
                indexData = [:]
                for (key, value) in v as! [String: Any] {
                    //indexData[key] = value
                    if key == "Image" {
                        //let pathReference = Storage.storage().reference(withPath: value as! String)
                        print("before getImageData call")
                        self.getImageData(pathRef: value as! String, completion: {(someData) in
                            print("before assigning indexData[key]")
                            indexData[key] = someData
                            print("after assigning indexData[key]")
                        })
                    } else {
                        indexData[key] = value
                    }
                }
                indexDataArray.append(indexData)
            }
            completion(indexDataArray)
        })
    }

func getImageData(pathRef: String, completion: @escaping(UIImage) -> ()) {
    let pathReference = Storage.storage().reference(withPath: pathRef as! String)
    pathReference.getData(maxSize: 1 * 1614 * 1614, completion: { (data, error) in
        if let error = error {
            print(error)
        } else {
            let image = UIImage(data:data!)
            print("called before completion handler w/ image")
            completion(image!)
        }
    })
}

我不知道我是否正确地接近这一点,但我想我是。我也猜测getData调用是异步的,这就是为什么它会在显示表视图后总是下载。

2 个答案:

答案 0 :(得分:1)

你不能这样做。

从Firebase发出请求。

随着时间的推移,您将收到许多回复 - 所有信息和所有不断变化的信息。

当每个新项目到达时 - 并且不要忘记它可能是添加或删除 - 更改您的表格以便显示所有当前项目

那是OCC!

OCC"偶尔会连接计算"。类似的短语是"离线首次计算"。因此,每当您使用任何主要服务时,您每天都会使用像Facebook,Snapchat等那样的OCC":无论您是否拥有带宽,一切都保持同步。你懂?当前设备 - 云计算的主要范例。

答案 1 :(得分:0)

编辑 - 请参阅Fattie关于prepareForReuse()的评论!

使用可重复使用的表格单元格,单元格将首先具有默认情况下/ xib上的外观。一旦他们使用",他们就会拥有他们设置的任何数据。这可能会导致一些不稳定的行为。我在我的"默认"中发现了一个问题。根据我的数据,我没有做任何事情,因为它已经匹配了xib,但如果数据的属性不同,我更新了外观。结果是上下滚动非常快,一些应该具有默认外观的东西具有改变的外观。

一个不显示上一个图像的基本解决方案是显示占位符/空图像,然后调用异步读取图像。不完全是你想要的,因为单元格仍会显示为空...

确保您拥有图片的本地商店,否则您将在向上和向下滚动时为您已有的图片提出服务器请求!

我建议你在viewDidLoad中调用一个方法来一次获取所有图像,然后,一旦你拥有它们,在你的成功处理程序中,调用self.tableview.reloadData()来显示所有图像