我有一个带有多个返回节点的firebase快照:
并尝试使用"for循环“来遍历它。在每个循环中,我想从Firebase Storage下载一个镜像文件:
let projectReviews = projectDB.queryOrdered(byChild: "contractorID").queryEqual(toValue: contractorID)
projectReviews.observeSingleEvent(of: .value, with: { snapshot in
for child in snapshot.children.allObjects as! [DataSnapshot] {
guard let value = child.value as? [String: AnyObject] else { continue }
if value["projectStatus"] as? String ?? "" == "Completed" && value["recommend"] != nil {
counter += 1
print("this is how many times this for loop has go through \(counter) at \(child.key)")
//Fetch and display the data.
var downloadURL :String
downloadURL = "Projects/" + "\(child.key)" + "--00"
print("---" + downloadURL)
print("downloadURL before download---" + downloadURL )
var imgURL = self.storageRef.child("")
imgURL = self.storageRef.child(downloadURL)
print("downloadURL after assign download URL ---" + downloadURL )
imgURL.getData(maxSize: Int64(1 * 1024 * 2000), completion: { (data, error) in
if let error = error {
print(error)
print("===This is image Download error on=== \n")
print(counter)
print("\(downloadURL)")
return
} else {
//Do something
}
})
}正如您在这里看到的,我使用了几个打印命令来告诉我downloadURL变量是怎么回事。
问题是:
在第二个循环中,当实际尝试下载文件时,downloadURL变量仍然使用前一个循环的值,即使在"getData“之前该值是正确的:
this is how many times this for loop has go through 1 at vzzzzzzzzzzzzzz----0001
---Projects/vzzzzzzzzzzzzzz----0001--00
downloadURL before download---Projects/vzzzzzzzzzzzzzz----0001--00
downloadURL after assign download URL ---Projects/vzzzzzzzzzzzzzz----0001--00
this is how many times this for loop has go through 2 at vzzzzzzzzzzzzzz----0002
---Projects/vzzzzzzzzzzzzzz----0002--00
downloadURL before download---Projects/vzzzzzzzzzzzzzz----0002--00
downloadURL after assign download URL ---Projects/vzzzzzzzzzzzzzz----0002--00
Error Domain=FIRStorageErrorDomain Code=-13010 "Object Projects/vzzzzzzzzzzzzzz----0001--00 does not exist." UserInfo={object=Projects/vzzzzzzzzzzzzzz----0001--00, bucket=bafo-1c3c8.appspot.com, ResponseBody=<?xml version='1.0' encoding='UTF-8'?><Error><Code>NoSuchKey</Code><Message>The specified key does not exist.</Message><Details>No such object: bafo-1c3c8.appspot.com/Projects/vzzzzzzzzzzzzzz----0001--00</Details></Error>, data=<3c3f786d 6c207665 7273696f 6e3d2731 2e302720 656e636f 64696e67 3d275554 462d3827 3f3e3c45 72726f72 3e3c436f 64653e4e 6f537563 684b6579 3c2f436f 64653e3c 4d657373 6167653e 54686520 73706563 69666965 64206b65 7920646f 6573206e 6f742065 78697374 2e3c2f4d 65737361 67653e3c 44657461 696c733e 4e6f2073 75636820 6f626a65 63743a20 6261666f 2d316333 63382e61 70707370 6f742e63 6f6d2f50 726f6a65 6374732f 76353756 5467595a 4c685170 7a57486a 4c306131 6b733150 494a6d31 52695339 61574631 4f6a5854 63635963 524b6453 67525a6f 54473832 2d2d2d2d 30303031 2d2d3030 3c2f4465 7461696c 733e3c2f 4572726f 723e>, NSLocalizedDescription=Object Projects/vzzzzzzzzzzzzzz----0001--00 does not exist., ResponseErrorDomain=com.google.HTTPStatus, ResponseErrorCode=404}
Projects/vzzzzzzzzzzzzzz----0001--00正如您从日志中看到的,如果我在getData闭包中打印downloadURL变量,它将包含先前的值“vzzzzzzzzzzzzzz 0001”。
我正在做的方式受支持吗?如果没有,我如何解决它,使图像可以在相同的循环中显示?
发布于 2018-06-02 18:17:06
我认为问题出在时机上。您有异步调用,第一个是对FireBase DB的调用。您可以在其中的花括号中启动for循环,因此不存在计时问题,但是,您随后会在for循环中进行异步调用。在异步调用开始之前,for循环会烧完。您应该使用for循环来创建URL数组,然后在对get data的第二个异步调用中,使用URL数组运行第二个for循环。
发布于 2018-06-04 00:06:51
找到了解决方案。这应该能够适用于使用Firebase数据库进行异步调用的所有情况。
这是一个由两部分组成的解决方案。
首先,定义一个带有回调的函数来查询数据,并将其作为类存储在数组中:
func getList(callback: @escaping ((_ data:[reviewContent]) -> Void)) {
var contentArray :[content] = [content]()
let someDB = dbRef!.child("someDB")
let returns = someDB.queryOrdered(byChild: "contractorID").queryEqual(toValue: someValue)
returns.observe(.value, with: {(snapshot) in
print(snapshot.childrenCount)
for child in snapshot.children.allObjects as! [DataSnapshot] {
guard let value = child.value as? [String: AnyObject] else { continue }
let contentEntry = content()
contentEntry.ID = child.key
//store any additional values where defined in the class
contentArray.append(contentEntry)
}
print("Array now has \(contentArray.count)")
callback(contentArray)
}) {(error) in print(error.localizedDescription)}
}其次,在viewDidLoad()中运行此函数,并使用回调通过for循环使用数组条目:
getList { (data:[content]) in
print("this is data from call back" )
print(data)
for contentEntry in data {
print(contentEntry.ID)
imgURL = self.storageRef!.child(contentEntry.ID)
imgURL.getData(maxSize: Int64(1 * 1024 * 2000), completion: { (imageData, error) in
if let error = error {
print(error)
print("===This is image Download error on=== \n")
print("\(contentEntry.ID)")
return
} else {
print("===This is image Download URL was used=== \n")
print("\(contentEntry.ID)")
print(imageData)
}
})
}
}希望这能有所帮助。
注意,最好在第一部分中为要存储在数组中的数据定义一个类。这也使得第二部分中的回调变得容易得多。
https://stackoverflow.com/questions/50455975
复制相似问题