Когда новый пользователь создает учетную запись, функция, которая создает учетную запись, устанавливает обработчик аутентификации, прежде чем пользователь и его изображение профиля могут быть полностью записаны в Firebase Storage и Firebase Firestore. Обработчик перемещает приложение на другую страницу, где viewDidLoad начинает извлекать фид на основе информации Firestore, но в этот момент пользователь не записывается.
func didSignUp() {
// Check the that the fields are not empty
guard let name = nameField.text, !name.isEmpty else { return }
guard let email = emailField.text, !email.isEmpty else { return }
guard let password = passwordField.text, !password.isEmpty else { return }
guard let image = imageView.image else { return }
// If successful thus far, create a user
Auth.auth().createUser(withEmail: email, password: password) { (user, error) in
// If there is no error creating a user
if error == nil {
// Reset the input fields
self.nameField.text = nil
self.emailField.text = nil
self.passwordField.text = nil
self.imageView.image = UIImage(named: "New User")
// Upload the profile image to Firebase Storage
self.uploadProfileImage(image, completion: { (url) in
// Check to see if url is returned
if url == nil {
print("Unable to upload profile image")
}
// Try to set the user's displayName and photoURL with a changeRequest
let changeRequest = Auth.auth().currentUser?.createProfileChangeRequest()
changeRequest?.displayName = name
changeRequest?.photoURL = url
changeRequest?.commitChanges(completion: { (error) in
// If there is an error, alert user
if error != nil {
print("Error commiting change request: \(error!.localizedDescription)")
}
// Once change request has succeeded, save profile to Firebase Firestore
self.saveProfile(name: name, photoURL: url!) { success in
if !success {
print("Failed to save user to Firestore")
} else {
self.navigateUserToHomePage()
}
}
})
})
} else {
let alertController = UIAlertController(title: "Error Creating Account", message: error?.localizedDescription, preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertController.addAction(defaultAction)
self.present(alertController, animated: true, completion: nil)
}
}
}
Должен ли я использовать Grand Central Dispatch для асинхронного выполнения некоторого кода?
edit: я загрузил функции Firebase
// Upload image data to Firebase Storage and return a URL of image if successful
func uploadProfileImage(_ image: UIImage, completion: @escaping (_ url: URL?) ->()) {
// Create reference to the profile pictures and save as uid.jpg
guard let uid = Auth.auth().currentUser?.uid else { return }
let storageRef = Storage.storage().reference().child("profile_pictures/\(uid).jpg")
// Compress UIImage to jpegData
guard let imageData = image.jpegData(compressionQuality: 0.5) else { return }
// Create the file metadata
let metadata = StorageMetadata()
metadata.contentType = "image/jpeg"
// Upload the image and metadata to the object profile_pictures/uid.jpg
storageRef.putData(imageData, metadata: metadata) { (metadata, error) in
// Check for errors in uploading data to Firebase Storage
guard metadata != nil, error == nil else {
print(error?.localizedDescription ?? "error")
completion(nil)
return
}
// Get access to the the download URL after upload
storageRef.downloadURL(completion: { (url, error) in
// Check for errors in accessing download URL
guard let downloadURL = url else {
print("Couln't get profile image url")
return
}
// Return download URL of uploaded image
completion(downloadURL)
})
}
}
// Save user data to Firebase Firestore
func saveProfile(name: String, photoURL: URL, completion: @escaping (Bool) -> ()) {
guard let uid = Auth.auth().currentUser?.uid else { return }
// Create data to save as a dictionary of [String: Any]
let userToSave: [String: Any] = [Constants.UserKeys.uid: uid,
Constants.UserKeys.name: name,
Constants.UserKeys.photoURL: photoURL.absoluteString]
// Create a document reference for Firestore
docRef = Firestore.firestore().collection("users").document(uid)
// Save data to Firestore reference
docRef.setData(userToSave) { (error) in
if let error = error {
print("Error saving to Firestore: \(error.localizedDescription)")
completion(false)
}
completion(true)
}
}