我知道我错过了一些简单的事情,但我花了好几个小时试图解决这个问题。除了没有图像,我的所有代码都可以正常运行。这是空白的。为什么呢?
func loadMembers4(completion: @escaping ([User]) -> ()) {
var usersArray = [User]()
ref.child("members").observeSingleEvent(of: .value, with: { (snapshot) in
for item in snapshot.children {
if let snap = item as? FIRDataSnapshot {
if let value = snap.value as? [String : Any] {
let birthday = value["birthday"] as! Int
let childParent = value["childParent"] as! String
let firstName = value["firstName"] as! String
let gender = value["gender"] as! String
let passcode = value["passcode"] as! Int
let profileImageUrl = value["profileImageUrl"] as! String
// get image
self.loadMemberProfilePict4(userProfileImageUrl: profileImageUrl, completion: { (userImage) in
let user = User(profilePhoto: userImage, userFirstName: firstName, userBirthday: birthday, userPasscode: passcode, userGender: gender, isUserChildOrParent: childParent)
usersArray.append(user)
usersArray.sort(by: {$0.birthday > $1.birthday})
})
}
}
}
completion(usersArray)
})
}
func loadMemberProfilePict4(userProfileImageUrl: String, completion: @escaping (UIImage) -> ()) {
var userImage = UIImage()
let storageRef = FIRStorage.storage().reference(forURL: userProfileImageUrl)
print(userProfileImageUrl)
storageRef.data(withMaxSize: 1 * 1024 * 1024, completion: { (imageData, error) in
let profileImage = UIImage(data: imageData!)
userImage = profileImage!
})
completion(userImage)
}
ViewDidLoad
方法:
loadMembers4 { (usersArray) in
print(usersArray.count)
self.currentUserName = usersArray[1].firstName
self.instructionsLabel.text = "Choose daily and weekly job assignments for \(usersArray[1].firstName)."
self.userImage.image = usersArray[1].photo
}
我知道图片是从Firebase获取的,因为当我在userProfileImageUrl
函数中打印loadMemberProfilePict4
时,会打印出正确的Firebase存储位置。但是当我在ViewDidLoad
中调用它时,图像显示为空白。什么都没有。
有什么想法吗?再一次,我确信它是一种简单的东西,我可以俯视,只需要一双新眼睛来指出它。谢谢!
编辑#1:
如果我打印出loadMembersProfilePict4
方法中的内容,则会显示以下内容:
func loadMemberProfilePict4(userProfileImageUrl: String, completion: @escaping (UIImage) -> ()) {
var userImage = UIImage()
let storageRef = FIRStorage.storage().reference(forURL: userProfileImageUrl)
print("UserProfileURL: ",userProfileImageUrl) // returns 4 strings of https://firebasestorage.google... (all correct)
storageRef.data(withMaxSize: 1024 * 1024) { (imageData, error) in
print("ImageData: ",imageData ?? "no data found!") // returns 21061 bytes, 7668 bytes, 44887 bytes, 8995 bytes (is this right?)
let profileImage = UIImage(data: imageData!)
userImage = profileImage!
print("UserImage: ",userImage.images ?? "no images found!") // returns "no images found!"
}
completion(userImage)
}
所以看起来图像不能正确加载?我不明白。我在项目的另一部分中使用了完全相同的代码,并且可以很好地加载用户图像。到底是怎么回事? AARGH!太令人沮丧了。
答案 0 :(得分:2)
我只是将userName的两行和viewDidLoad()方法的图像放入相应方法的完成块中。从viewDidLoad()中删除这些行。
func loadMemberProfilePict4(userProfileImageUrl: String, completion: @escaping (UIImage) -> ()) {
var userImage = UIImage()
let storageRef = FIRStorage.storage().reference(forURL: userProfileImageUrl)
print(userProfileImageUrl)
storageRef.data(withMaxSize: 1 * 1024 * 1024, completion: { (imageData, error) in
let profileImage = UIImage(data: imageData!)
userImage = profileImage!
self.userImage.image = profileImage
})
completion(userImage)
}
对于Username,将其他行放在loadMembers4()的完成块中
func loadMembers4(completion: @escaping ([User]) -> ()) {
var usersArray = [User]()
ref.child("members").observeSingleEvent(of: .value, with: { (snapshot) in
for item in snapshot.children {
if let snap = item as? FIRDataSnapshot {
if let value = snap.value as? [String : Any] {
let birthday = value["birthday"] as! Int
let childParent = value["childParent"] as! String
let firstName = value["firstName"] as! String
let gender = value["gender"] as! String
let passcode = value["passcode"] as! Int
let profileImageUrl = value["profileImageUrl"] as! String
// get image
self.loadMemberProfilePict4(userProfileImageUrl: profileImageUrl, completion: { (userImage) in
let user = User(profilePhoto: userImage, userFirstName: firstName, userBirthday: birthday, userPasscode: passcode, userGender: gender, isUserChildOrParent: childParent)
**self.currentUserName = user.firstName**
self.instructionsLabel.text = "Choose daily and weekly job assignments for \(user.firstName)."
usersArray.append(user)
usersArray.sort(by: {$0.birthday > $1.birthday})
})
}
}
}
completion(usersArray)
})
}
答案 1 :(得分:0)
这就是您的代码为空的原因:
// #1
var userImage = UIImage()
// #2
storageRef.data(withMaxSize: 1 * 1024 * 1024, completion: { (imageData, error) in
// #4
let profileImage = UIImage(data: imageData!)
userImage = profileImage!
})
// #3
completion(userImage)
因为下载数据是异步的,所以存在竞争条件。这意味着您在下载图像之前返回空图像。通过执行以下操作来修复它:
// #1
var userImage = UIImage()
// #2
storageRef.data(withMaxSize: 1 * 1024 * 1024, completion: { (imageData, error) in
// #3
completion(UIImage(data: imageData!))
})
应该解决问题。
答案 2 :(得分:0)
因此,在过去两天试图找出解决方案之后,我得出结论,由于某种原因,Swift不允许我进行嵌入式@escaping
闭包。我可以创建单独的@escaping
闭包,它们都可以工作,但是如果我把一个放在另一个里面,第二个就不能正常执行。
所以这就是我最终做的事情:
功能#1 获取用户的Firebase数据,包括用户的网址字符串'存储在Firebase存储上的照片。
func loadMembers(completion: @escaping ([UserClass]) -> ()) {
var usersArray = [UserClass]()
ref.child("members").observeSingleEvent(of: .value, with: { (snapshot) in
for item in snapshot.children {
if let snap = item as? FIRDataSnapshot {
if let value = snap.value as? [String : Any] {
let birthday = value["birthday"] as! Int
let childParent = value["childParent"] as! String
let firstName = value["firstName"] as! String
let gender = value["gender"] as! String
let passcode = value["passcode"] as! Int
let profileImageUrl = value["profileImageUrl"] as! String
let user = UserClass(userProfileImageURL: profileImageUrl, userFirstName: firstName, userBirthday: birthday, userPasscode: passcode, userGender: gender, isUserChildOrParent: childParent)
usersArray.append(user)
usersArray.sort(by: {$0.birthday > $1.birthday})
}
}
}
completion(usersArray)
})
}
功能#2:从第一个功能获取网址字符串并使用它来加载用户'来自Firebase的图片。然而,这并没有给我完整的图像数组,因为它一次一个地加载它们。它不会给我count: 4
,而是会给我count: 1, count: 2, count: 3, count: 4
。
因此,当我加载视图控制器时,图像会在着陆到正确的用户之前循环通过每个用户。不理想。
// WORKS BEST, BUT IMAGES CYCLE THRU ALL USERS
func loadMemberProfilePict(userImageURL: String, userFirstName: String, userBirthday: Int, userPasscode: Int, userGender: String, userChildParent: String, completion: @escaping ([User]) -> ()) {
let storageRef = FIRStorage.storage().reference(forURL: userImageURL)
storageRef.data(withMaxSize: 1 * 1024 * 1024, completion: { (data, error) in
let pic = UIImage(data: data!)
let user = User(profilePhoto: pic!,
userFirstName: userFirstName,
userBirthday: userBirthday,
userPasscode: userPasscode,
userGender: userGender,
isUserChildOrParent: userChildParent)
self.users.append(user)
self.users.sort(by: {$0.birthday > $1.birthday})
completion(self.users)
})
}
功能#3:导致此功能,我使用简单的'if'
语句等待所有用户加载后再显示在视图上。
在ViewDidLoad
:
loadMembers { (usersArray) in
var memberImageCount = 0
for user in usersArray {
self.loadMemberProfilePict(userImageURL: user.imageURL, userFirstName: user.firstName, userBirthday: user.birthday, userPasscode: user.passcode, userGender: user.gender, userChildParent: user.childParent, completion: { (usersIntermediateArray) in
memberImageCount += 1
if memberImageCount == usersArray.count {
self.users = usersIntermediateArray
self.userImage.image = self.users[3].photo
self.currentUserName = self.users[3].firstName
self.instructionsLabel.text = "Choose daily and weekly job assignments for \(self.users[3].firstName)."
self.navigationItem.title = self.users[3].firstName
}
})
}
}
我不知道这是否是最佳做法,但它的功能是否正常,我希望它可以帮助将来可能遇到同样问题的人。