简体   繁体   English

将图像保存到文档目录后更新bool变量无法在Swift中正常工作

[英]Updating a bool variable after saving image to documents directory doesn’t work as expected in Swift

I am working on the user profile page of my app. 我正在我的应用程序的用户个人资料页面上。 I've got a global bool variable (updateProfile) that is set to false by default. 我有一个全局布尔变量(updateProfile),默认情况下将其设置为false。 When the user makes any change to their profile info, like change/remove their profile picture, the database is updated and the image is downloaded and saved in the documents directory. 当用户对其个人资料信息进行任何更改(例如更改/删除其个人资料图片)时,将更新数据库,并下载图像并将其保存在documents目录中。 Here is the code where that image is saved after downloading: 这是下载后保存该图像的代码:

struct Downloads {

    // Create a static variable to start the download after tapping on the done button in the editUserProfile page
    static var updateProfile: Bool = false

    static func downloadUserProfilePic() {

        Database.database().reference().child("Users").child(userID!).child("Profile Picture URL").observeSingleEvent(of: .value) { (snapshot) in
        guard let profilePictureString = snapshot.value as? String else { return }
        guard let profilePicURL = URL(string: profilePictureString) else { return }

        let session = URLSession(configuration: .default)

        let downloadPicTask = session.dataTask(with: profilePicURL) {
                (data, response, error) in

            if let e = error {
                print("error downloading with error: \(e)")

            } else {
                if let res = response as? HTTPURLResponse {
                    Downloads.imageCached = true // The image has been downloaded
                    print("Downloaded with \(res.statusCode)")

                    if let imageData = data {
                        let image = UIImage(data: imageData)

                        // Now save the image in the documents directory
                        // Get the url of the documents directory
                        let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
                        // Name your image with the user ID to make it unique
                        let imageName = userID! + "profilePic.jpg"
                        // Create the destination file URL to save the image
                        let imageURL = documentsDirectory.appendingPathComponent(imageName)
                        print(imageURL)
                        let data = image?.jpegData(compressionQuality: 0.5)

                        do {
                            // Save the downloaded image to the documents directory

                            // Write the image data to disk
                            try data!.write(to: imageURL)
                            print("Image Saved")
                            updateProfile = true

                        } catch {
                            print("Error saving file \(error)")
                        }


                    } else {
                        print("Couldnt get image")
                    }

                } else {
                    print("Couldnt't get response")
                }
            }
        }
        downloadPicTask.resume()        

    }
}

SomeOtherViewController SomeOtherViewController

// When the user taps on the 'done' button
@objc func doneButtonTapped() {

    uploadUserSelectedPicture()

}

func uploadUserSelectedPicture() {

    // Download the profile picture and save it
    Downloads.downloadUserProfilePic()

    if Downloads.updateProfile == true {
        // Go to the user profile page
        let userProfilePage = UserProfilePage()
        self.present(userProfilePage, animated: true)
    }

}

As you can see, I am printing "Image saved" as soon as the image is saved to the documents directory and also the updateProfile global variable is changed to true. 如您所见,将图像保存到documents目录并且将updateProfile全局变量更改为true后,我将立即打印“已保存图像”。 And on SomeOtherViewController, a page is presented (when tapped on the done button) only if the updateProfile variable is true (Which means the image should be saved to the documents directory). 并且在SomeOtherViewController上,仅当updateProfile变量为true(表示图像应保存到documents目录)时,才会显示页面(在完成按钮上点击)。

But the only problem is, the variable is set to true before the image is saved, how do I know this? 但是唯一的问题是,在保存图像之前将变量设置为true,我怎么知道这一点? I know this because the page is presented before the execution of the print statement print("Image Saved") . 我知道这是因为页面是在执行打印语句print("Image Saved") Why does this happen? 为什么会这样? Is there any way I could get rid of this problem? 有什么办法可以摆脱这个问题?

Actually your code is supposed to never present the page. 实际上,您的代码应该永远不会显示该页面。 But as you forgot to set updateProfile explicitly to false before calling downloadUserProfilePic the page is presented without the image from the second call on. 但是,由于您在调用downloadUserProfilePic之前忘记将updateProfile显式设置为false ,因此页面呈现时没有第二次调用的图像。

Nevertheless both observe and dataTask work asynchronously. 不过这两个observedataTask异步工作。 You have to add a completion handler. 您必须添加完成处理程序。

Simple form: 简单的形式:

 
 
 
  
  static var updateProfile: Bool = false
 
  

static func downloadUserProfilePic(completion: @escaping () -> Void) {

...

    do {
       // Save the downloaded image to the documents directory

       // Write the image data to disk
       try data!.write(to: imageURL)
       print("Image Saved")          
       completion()
    }

...

func uploadUserSelectedPicture() {

    // Download the profile picture and save it
    Downloads.downloadUserProfilePic { [weak self] in
        // Go to the user profile page
        DispatchQueue.main.async {
           let userProfilePage = UserProfilePage()
           self?.present(userProfilePage, animated: true)
        }
    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM