我正在制作一个带有图片的tableView。图片是来自人们的个人资料图片,可以加入,离开并自己制作房间。在那个房间里,会显示tableView。
为了保存数据,我想在人们加入房间时将每个个人资料图片存储在文档目录中。现在这样做了,但是即使我两次调用它,tableView也会重新加载。因为它重新加载很多,所以它会因为数组超出索引而崩溃。
崩溃发生在图片阵列上,而不是用户名数组。这是我的代码(有点多):
private var playersRefHandle: FIRDatabaseHandle?
var channelRef: FIRDatabaseReference?
var players = [String]()
var playerImages = [UIImage]()
var playerUIDs = [String]()
var playersImageVersion = [String]()
var channel: Channel? {
didSet {
title = channel?.name
}
}
override func viewDidLoad() {
super.viewDidLoad()
playersView.delegate = self
playersView.dataSource = self
let storage = FIRStorage.storage()
let storageRef = storage.reference(forURL: "gs://X-f5beb.appspot.com")
channelRef?.observeSingleEvent(of: .value, with: { (snapshot) in
if let snapDict = snapshot.value as? [String:AnyObject]{
for each in snapDict{
let UIDs = each.value["userID"] as? String
let pictureVersion = each.value["PictureVersion"] as? String
if let allUIDS = UIDs{
if let allPictureVersions = pictureVersion{
self.playerUIDs.append(UIDs!)
self.playersImageVersion.append(allPictureVersions)
let userNames = each.value["username"] as? String
if let users = userNames{
self.players.append(users)
}
if self.checkDataExist(dataToCheck: "\(UIDs!)" + "Image.png") == false || self.isCurrentImageVersionStored(pathToImage: "\(UIDs!)" + "ImageVersion.txt", playersVersionImage: "\(allPictureVersions)") == false
{
print("image needs to be downloaded online")
let profilePicRef = storageRef.child((allUIDS)+"/profile_picture.png")
profilePicRef.data(withMaxSize: 1 * 500 * 500) { data, error in
if let error = error {
}
if (data != nil)
{
let image = UIImage(data: data!)
let convertImage = UIImagePNGRepresentation(image!)
let pathUIDImage = self.getDocumentsDirectory().appendingPathComponent(allUIDS + "Image.png")
try? convertImage!.write(to: pathUIDImage)
let playersUIDImageVersion = allPictureVersions
var pathUIDImageVersion = self.getDocumentsDirectory().appendingPathComponent(allUIDS + "ImageVersion.txt")
try? playersUIDImageVersion.write(to: pathUIDImageVersion, atomically: true, encoding: .utf8)
self.playerImages.append(UIImage (data: data!)!)
}
}
}
else
{
self.playerImages.append(self.retrieveImageFromDocuments(playersUID: UIDs!))
}
}
}
}
}
self.playersView.reloadData()
self.observePlayers()
})
}
deinit {
if let refHandle = playersRefHandle {
channelRef?.removeObserver(withHandle: refHandle)
}
}
override func willMove(toParentViewController parent: UIViewController?)
{
if parent == nil
{
print("back")
}
}
func getDocumentsDirectory() -> URL {
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let documentsDirectory = paths[0]
return documentsDirectory
}
func checkDataExist(dataToCheck: String) -> Bool
{
let documentsURL = try! FileManager().url(for: .documentDirectory,
in: .userDomainMask,
appropriateFor: nil,
create: true)
let file = documentsURL.appendingPathComponent(dataToCheck)
let fileExists = FileManager().fileExists(atPath: file.path)
if fileExists == true
{
return true
}
else
{
return false
}
}
func isCurrentImageVersionStored(pathToImage: String, playersVersionImage: String) -> Bool
{
if let dir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first {
let path = dir.appendingPathComponent(pathToImage)
do {
let currentStoredImage = try String(contentsOf: path, encoding: String.Encoding.utf8)
let currentStoredImageInt = Int(currentStoredImage)
let playersVersionImageInt = Int(playersVersionImage)
if currentStoredImageInt == playersVersionImageInt
{
return true
}
else
{
return false
}
}
catch {/* error handling here */}
return false
}
return false
}
func retrieveImageFromDocuments(playersUID: String) -> UIImage
{
print("image is available offline")
let nsDocumentDirectory = FileManager.SearchPathDirectory.documentDirectory
let nsUserDomainMask = FileManager.SearchPathDomainMask.userDomainMask
let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
let dirPath = paths.first
let imageURL = URL(fileURLWithPath: dirPath!).appendingPathComponent("\(playersUID)" + "Image.png")
let profileImageForUser = UIImage(contentsOfFile: imageURL.path)
return profileImageForUser!
}
func observePlayers()
{
playersRefHandle = channelRef?.child("username").observe(.childChanged, with: { (snapshot) -> Void in
print("added player")
})
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return players.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
print("configuring one of multiple cells")
print(playerImages.count)
print(players.count)
var cell = tableView.dequeueReusableCell(withIdentifier: "playersCell") as! PlayersCellInMultiplayer
cell.playersUsername?.text = players[indexPath.row] as String
cell.playersImage?.image = playerImages[indexPath.row] as UIImage
return cell
}
这是我打印的随机频道,其中包含少数用户:
image is available offline
image needs to be downloaded online
configuring one of multiple cells
1
2
configuring one of multiple cells
1
2
为什么会这样?这是异步方法吗?解决问题的最佳方法是什么?