Firebase iOS:为 TableView 下载图像 - 最佳实践

Firebase iOS: Download image for TableView - Best Practice

我遵循了 Ray Wenderlich (Link) 的 Firebase 教程,并采用了他使用观察方法的快照初始化对象的方式(在我的例子中是 "Location" 类型):

class 位置:

init(snapshot: FIRDataSnapshot) {
    identifier = snapshot.key
    let snapshotValue = snapshot.value as! [String : AnyObject]
    type = snapshotValue["type"] as! String
    name = snapshotValue["name"] as! String
    address = snapshotValue["address"] as! String
    latitude = Double(snapshotValue["latitude"] as! String)!
    longitude = Double(snapshotValue["longitude"] as! String)!
    avatarPath = snapshotValue["avatarPath"] as! String

    ref = snapshot.ref
}

LocationsViewController:

databaseHandle = locationsRef?.queryOrdered(byChild: "name").observe(.value, with: { (snapshot) in

        var newLocations:[Location] = []

        for loc in snapshot.children {
            let location = Location(snapshot: loc as! FIRDataSnapshot)

            newLocations.append(location)
        }

        self.locations = newLocations
        self.tableView.reloadData()
})

这真的很有效,但现在我正在尝试加载存储在存储引用 "avatarPath" 下的图像。 我的尝试成功了,但图像需要很长时间才能加载。有没有更好的way/place加载这些图片?

我的尝试1:

databaseHandle = locationsRef?.queryOrdered(byChild: "name").observe(.value, with: { (snapshot) in

        var newLocations:[Location] = []

        for loc in snapshot.children {
            let location = Location(snapshot: loc as! FIRDataSnapshot)

            newLocations.append(location)
        }

        self.locations = newLocations
        self.tableView.reloadData()

        //Load images       
        for loc in self.locations {
            let imagesStorageRef = FIRStorage.storage().reference().child(loc.avatarPath)
            imagesStorageRef.data(withMaxSize: 1*1024*1024, completion: { (data, error) in
                if let error = error {
                    print(error.localizedDescription)
                } else {
                    loc.avatarImage = UIImage(data: data!)!
                    self.tableView.reloadData()
                }
            })
        }
})

我的第二次尝试(在位置 class 内):

init(snapshot: FIRDataSnapshot) {
    identifier = snapshot.key
    let snapshotValue = snapshot.value as! [String : AnyObject]
    type = snapshotValue["type"] as! String
    name = snapshotValue["name"] as! String
    address = snapshotValue["address"] as! String
    latitude = Double(snapshotValue["latitude"] as! String)!
    longitude = Double(snapshotValue["longitude"] as! String)!
    avatarPath = snapshotValue["avatarPath"] as! String

    ref = snapshot.ref

    super.init()
    downloadImage()
}

func downloadImage() {
    let imagesStorageRef = FIRStorage.storage().reference().child(self.avatarPath)
    imagesStorageRef.data(withMaxSize: 1*1024*1024, completion: { (data, error) in
        if let error = error {
            print(error.localizedDescription)
        } else {
            self.avatarImage = UIImage(data: data!)!
        }
    })
}

提前致谢!

妮可

首先尝试将您的代码更改为:

DispatchQueue.main.async {
       for loc in self.locations {
            let imagesStorageRef = FIRStorage.storage().reference().child(loc.avatarPath)
            imagesStorageRef.data(withMaxSize: 1*1024*1024, completion: { (data, error) in
                if let error = error {
                    print(error.localizedDescription)
                } else {
                    loc.avatarImage = UIImage(data: data!)!
                    self.tableView.reloadData()
                }
            })
        }
}

实现此目的的最佳方法是在单元格函数的加载中异步加载。我的意思是:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
DispatchQueue.main.async {
   let imagesStorageRef = FIRStorage.storage().reference().child(self.locations[indexPath.row].avatarPath)
        imagesStorageRef.data(withMaxSize: 1*1024*1024, completion: { (data, error) in
            if let error = error {
                print(error.localizedDescription)
            } else {
                locations[indexPath.row].avatarImage = UIImage(data: data!)!
tableView.reloadRows(at indexPaths: [indexPath], with animation: .none)
            }
        })
    }

}