【问题标题】:Assigning a value to a variable after Firebase return result?Firebase返回结果后为变量赋值?
【发布时间】:2017-12-07 17:00:26
【问题描述】:

我已经为此苦苦挣扎了 2 个小时。我正在使用 Firebase 数据库和存储在 Swift 中构建一个应用程序。

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

问题在于,在我取回下载的 URL 之前,它显然分配了一个空的 String 的值(我已经声明了它们)。如果用户不更新图像但 UITextFields 的其余部分都可以正常工作,则旧 URL 将提交到 Firebase 数据库。

我的问题是如何从存储中执行下载的 URL 方法,然后将其分配给 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`

【问题讨论】:

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


    【解决方案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
        }
    }
    

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

    【讨论】:

    • 问题在于线程,是的。基本上,如果用户选择了新图像,则需要先上传它们,然后获取下载 URL,将它们分配给新变量,然后将它们与其余信息一起提交到数据库。您的代码的问题是在此之前不会执行 in 。我在想也许我必须将整个存储上传放在主队列(同步)上,以便它首先执行?但是 DispatchQueue.main.async { ... } 给了我一个 EXC_BAD_INSTRUCTION 错误,这让我发疯了
    • 我现在很困惑,不知道是什么问题,你想在下载完成之前和下载完成之后执行相同的代码吗?
    • 很抱歉让您感到困惑。执行存储函数后需要执行代码(因此,变量 storageHeaderDownloadedURL 和 storageProfileDownloadedURL 都将具有 URL(字符串)值,之后将在 switch 语句中使用它们以获取正确的图像 url)。据我了解,您的代码意味着它必须在存储上传/下载功能中执行。整个问题是存储上传/下载URL代码的代码没有首先执行,我看不出你的代码是如何改变的
    • if let profileImgDownloadedURL = url?.absoluteString ---> 这发生在未先执行的存储上传中。
    • 要么我不理解您的问题,要么我无法正确解释我的解决方案。大概是先入为主。为了以防万一,我会尽量解释我写的更好一点。 if let profileImgDownloadedURL = url?.absoluteString 是 storageUserProfileID.downloadURL 回调的一部分。所以它不会在下载完成之前执行,因此你的 self.storageProfileDownloadedURL 不会为空。只有在两个下载完成后,下面的代码才会运行(这是通过移动一个函数并通过枚举处理来完成的)。这不是你想要达到的目标吗?
    猜你喜欢
    • 2015-12-18
    • 1970-01-01
    • 2018-03-17
    • 1970-01-01
    • 2017-02-25
    • 2012-09-08
    • 2017-03-20
    • 2020-11-04
    相关资源
    最近更新 更多