Firebase存储空间图像空白

时间:2017-10-05 03:07:52

标签: swift firebase firebase-storage

我知道我错过了一些简单的事情,但我花了好几个小时试图解决这个问题。除了没有图像,我的所有代码都可以正常运行。这是空白的。为什么呢?

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!太令人沮丧了。

3 个答案:

答案 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
                }
            })
        }
    }

我不知道这是否是最佳做法,但它的功能是否正常,我希望它可以帮助将来可能遇到同样问题的人。