在Firebase返回结果后为变量赋值?

时间:2017-07-04 09:35:57

标签: ios swift firebase-realtime-database firebase-authentication firebase-storage

我一直在努力奋斗2个小时。我正在使用Firebase数据库和存储在Swift中构建应用程序。

目标是更新用户个人资料。用户有2个图像 - 配置文件和标题。现在,我必须首先检查他们是否从照片库中选择了一个图像,如果没有 - 只需从数据库中获取旧URL并将其与其他更新信息一起提交回数据库。如果是新选择的图片,请将图片上传到存储,然后使用downloadURL将其分配给var storageHeaderDownloadedURL和/或var storageProfileDownloadedURL并使用其余部分提交字符串值用户数据到Firebase数据库。

问题在于,它显然会在返回下载的URL之前分配空String的值(我已经声明了它们)。如果用户未更新图片,但UITextFields的其余部分全部有效,则会将旧网址提交给Firebase数据库。

我的问题是如何从存储中执行下载的网址方法,然后直接将其分配给var storageHeaderDownloadedURLvar storageProfileDownloadedURL

func updateUserProfile ()
{
    if let userID = FIRAuth.auth()?.currentUser?.uid
    {
        // Note: Storage references to profile images & profile headers folder
        let storageUserProfileID = Storage.storage.profile_images.child(userID)
        let storageUserHeaderID = Storage.storage.profile_headers.child(userID)

        guard let imageProfile = profileImage.image else { return }

        guard let headerImage = headerImage.image else { return }


        if let newProfileImage = UIImagePNGRepresentation(imageProfile), let newHeaderImage = UIImagePNGRepresentation(headerImage)
            {
                storageUserProfileID.put(newProfileImage, metadata: nil, completion: { (metadata, error) in

                    if error != nil
                    {
                        showAlert(title: "Oops!", msg: (error?.localizedDescription)!, actionButton: "OK", viewController: self)
                        return
                    }
                    // Get the URL from the storage
                    storageUserProfileID.downloadURL(completion: { (url, error) in

                        if error != nil
                        {
                            showAlert(title: "Oops!!!", msg: (error?.localizedDescription)!, actionButton: "OK", viewController: nil)
                            return
                        }
                        else
                        {
                            if let profileImgDownloadedURL = url?.absoluteString
                            {
                                self.storageProfileDownloadedURL = profileImgDownloadedURL
                                print(self.storageProfileDownloadedURL)
                                self.selectedProfileImage = .True
                            }
                        }

                    })
                })
                storageUserHeaderID.put(newHeaderImage, metadata: nil, completion: { (metadata, error) in

                    if error != nil
                    {
                        showAlert(title: "Oops!", msg: (error?.localizedDescription)!, actionButton: "OK", viewController: self)
                        return
                    }

                    // Get the URL from the storage
                    storageUserHeaderID.downloadURL(completion: { (url, error) in

                        if error != nil
                        {
                            showAlert(title: "Oops!!!", msg: (error?.localizedDescription)!, actionButton: "OK", viewController: self)
                            return
                        }
                        else
                        {
                            if let headerImgDownloadedURL = url?.absoluteString
                            {
                                self.storageHeaderDownloadedURL = headerImgDownloadedURL
                                print(self.storageHeaderDownloadedURL)
                                self.selectedHeaderImage = .True
                            }
                        }
                    })
                })


        //Note: Update the info for that user in Database


        print(self.storageHeaderDownloadedURL)
        print(self.storageProfileDownloadedURL)


        var finalHeaderImageURL = String()

        switch self.selectedHeaderImage {

        case .True:
            finalHeaderImageURL = self.storageHeaderDownloadedURL
            break

        case .False:
            finalHeaderImageURL = self.oldHeaderImageInDB
            break

        }
        print(finalHeaderImageURL)


        var finalProfileImageURL = String()

        switch self.selectedProfileImage {

        case .True:
            finalProfileImageURL = self.storageProfileDownloadedURL
            break

        case .False:
            finalProfileImageURL = self.oldProfilePhotoImageInDB
            break

        }
        print(finalProfileImageURL)

        guard let newDisplayName = self.displayNameTextField.text else { return }
        guard let newLocation = self.locationTextField.text else { return }
        guard let newDescription = self.bioTextField.text else { return }
        guard let newWebsite = self.websiteTextField.text else { return }
        guard let newBirthday = self.birthdayTextField.text else { return }

        let newUpdatedUserDictionary = ["imageProfile": finalProfileImageURL,
                                        "imageHeader" : finalHeaderImageURL,
                                        "description" : newDescription,
                                        "location": newLocation,
                                        "displayName": newDisplayName,
                                        "website": newWebsite,
                                        "birthday": newBirthday,
                                        ]
        Database.dataService.updateUserProfile(uid: userID, user: newUpdatedUserDictionary)

        showAlert(title: "Hey", msg: "Your profile was updated", actionButton: "OK", viewController: self)
         } // Get new uploaded profile and header image URLs
    }
}

我用于switch语句的枚举,以确定它是旧URL还是新URL:

 enum SelectedHeaderImage
 {
  case True
  case False
 }

 enum SelectedProfileImage
 {
 case True
 case False
 }

班级出口:

var storageProfileDownloadedURL = String()
var storageHeaderDownloadedURL = String()  

var oldProfilePhotoImageInDB = String()
var oldHeaderImageInDB = String()

var selectedHeaderImage = SelectedHeaderImage.False
var selectedProfileImage = SelectedProfileImage.False`

1 个答案:

答案 0 :(得分:1)

据我所知,你的问题在于排队。您希望下载代码在下载完成后执行,但它在正常流程中执行。如果这就是您的问题,那么我建议您创建另一个enum,其中包含三个下载状态/计数。并移动下面的代码,您希望稍后在函数中执行。下载完成后,增加新enum的状态。它看起来像这样:

enum DownloadCount
{
    case Zero
    case One
    case Two
}
var downloadCount = DownloadCount.Zero

并且在您下载的每个成功块中完成更改后,我将在此处写一个,以便您了解需要完成的工作。

if let profileImgDownloadedURL = url?.absoluteString
{
     self.storageProfileDownloadedURL = profileImgDownloadedURL
     print(self.storageProfileDownloadedURL)
     self.selectedProfileImage = .True
     if(downloadCount == .Zero)
     {
         downloadCount = DownloadCount.One
     }
     else
     {
         downloadCount = DownloadCount.Two
     }
     self.newAssigningFunction()
}

func newAssigningFunction()
{
    if(downloadCount == .Two)
    {
        //Do your storage/saving work here
    }
}

此外,如果您需要再次执行此功能,最好在downloadCount功能开始时将Zero设置回updateUserProfile。如果有些不清楚,或者您需要进一步的帮助,请告诉我。或者如果这不是你的情况。