在将图像保存到文档目录后更新 bool 变量在 Swift 中没有按预期工作
Updating a bool variable after saving image to documents directory doesn’t work as expected in Swift
我正在处理我的应用程序的用户个人资料页面。我有一个默认设置为 false 的全局 bool 变量 (updateProfile)。当用户对他们的个人资料信息进行任何更改时,例如 change/remove 他们的个人资料图片,数据库会更新,图像会被下载并保存在文档目录中。这是下载后保存图像的代码:
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
// 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)
}
}
如您所见,我在将图像保存到文档目录并且 updateProfile 全局变量更改为 true 后立即打印 "Image saved"。在 SomeOtherViewController 上,仅当 updateProfile 变量为 true 时(这意味着图像应保存到文档目录)才会显示页面(当点击完成按钮时)。
但唯一的问题是,在保存图像之前变量设置为 true,我怎么知道的?我知道这一点是因为页面是在执行 print 语句 print("Image Saved")
之前呈现的。为什么会这样?有什么办法可以解决这个问题吗?
实际上您的代码应该永远不会显示页面。但是,由于您在调用 downloadUserProfilePic
之前忘记将 updateProfile
显式设置为 false
,因此显示的页面没有第二次调用时的图像。
然而,observe
和 dataTask
都是异步工作的。您必须添加一个完成处理程序。
简单形式:
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)
}
}
}
我正在处理我的应用程序的用户个人资料页面。我有一个默认设置为 false 的全局 bool 变量 (updateProfile)。当用户对他们的个人资料信息进行任何更改时,例如 change/remove 他们的个人资料图片,数据库会更新,图像会被下载并保存在文档目录中。这是下载后保存图像的代码:
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
// 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)
}
}
如您所见,我在将图像保存到文档目录并且 updateProfile 全局变量更改为 true 后立即打印 "Image saved"。在 SomeOtherViewController 上,仅当 updateProfile 变量为 true 时(这意味着图像应保存到文档目录)才会显示页面(当点击完成按钮时)。
但唯一的问题是,在保存图像之前变量设置为 true,我怎么知道的?我知道这一点是因为页面是在执行 print 语句 print("Image Saved")
之前呈现的。为什么会这样?有什么办法可以解决这个问题吗?
实际上您的代码应该永远不会显示页面。但是,由于您在调用 downloadUserProfilePic
之前忘记将 updateProfile
显式设置为 false
,因此显示的页面没有第二次调用时的图像。
然而,observe
和 dataTask
都是异步工作的。您必须添加一个完成处理程序。
简单形式:
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)
}
}
}