如何从 Firebase Storage 下载照片并为当前用户替换最后一张

How to download a photo from Firebase Storage and replace the last one for the current user

我正在尝试从 Firebase 下载照片用户帐户。 我解释我的问题: 在用户的个人资料页面上,有一个按钮显示他当前的头像作为他的个人资料头像,首先按钮背景中没有图像,当他第一次点击时他可以选择他的照片库中的图像或者通过设备相机(通过警报控制器),然后将此图像或照片上传到 Firebase 存储中,并且新照片显示在按钮背景上。

但是当用户想要改变他当前的照片时,他再次点击按钮并选择或拍照,但是在他这样做之后,按钮背景没有改变,这意味着用户改变了他的照片但是当前页面的照片不会更新更改,但如果我转到另一个视图并返回更改照片视图,则用户刚刚选择的正确照片位于按钮背景中。所以下载可以很好地工作,但如果用户没有去另一个视图,则不会立即下载。有点难解释。

这是我的上传方式代码:

// Variables I need
@IBOutlet weak var photoProfil: UIButton!
var name: String!
var userUid: String!
@IBOutlet var userImagePicker: UIImageView!
var imagePicker: UIImagePickerController!
var imageSelected = false
var isUploaded: Bool = false
var refDatabase: DatabaseReference!
var photovide: UIImage = UIImage(named:"profilvide")!

// Take a photo with the camera (first choice)
func takePhoto(_ sender: Any) {
    if UIImagePickerController.isSourceTypeAvailable(.camera) {
        imagePicker.delegate = self
        imagePicker.allowsEditing = false
        imagePicker.sourceType = UIImagePickerControllerSourceType.camera // Source Camera
        self.present(imagePicker, animated: false, completion: nil)
    } else { // If camera doesn't work
        imagePicker.delegate = self
        imagePicker.allowsEditing = false

        imagePicker.sourceType = UIImagePickerControllerSourceType.photoLibrary // Source Library
        self.present(imagePicker, animated: false, completion: nil)
    }
}

// Choose an image from the library
func libraryPhoto(sender: AnyObject) {
    let image = UIImagePickerController()
    image.delegate = self
    image.sourceType = UIImagePickerControllerSourceType.photoLibrary
    image.allowsEditing = false
    self.present(image, animated: true)
}

// Take this image and shows it on the View Controller
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String: Any]) {
    // I want to upload the photo to storage and save it in the database
    if let image = info[UIImagePickerControllerOriginalImage] as? UIImage {
        photoProfil.setImage(image, for: .normal) // Button showing the user photo
        userImagePicker.image = image
        imageSelected = true
        uploadImg()
    } else {
        print("Error...")
    }

    imagePicker.dismiss(animated: true, completion: nil)
    self.dismiss(animated: true, completion: nil)
}

// The alert Controller
@IBAction func actionButton(_ sender: Any) {
    let attributedString = NSAttributedString(string: "User photo", attributes: [
        NSFontAttributeName : UIFont.boldSystemFont(ofSize: 15),
        NSForegroundColorAttributeName : UIColor.black
        ])

    let alertController = UIAlertController(title: "", message: "", preferredStyle: .actionSheet)
    alertController.message = nil
    alertController.setValue(attributedString, forKey: "attributedTitle")
    alertController.addAction(UIAlertAction(title: "Take photo", style: .default, handler: self.takePhoto))
    alertController.addAction(UIAlertAction(title: "Choose in Library", style: .default, handler: self.libraryPhoto))
    alertController.addAction(UIAlertAction(title: "Show current photo", style: .default, handler: self.showPhoto))
    alertController.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
    self.present(alertController, animated: true, completion: nil)
}

// Create a path in order to save the photo in Firebase
func setUser(img: String) {
    var userUid = Auth.auth().currentUser?.uid
    let userData = [
                    "nickname": Auth.auth().currentUser?.displayName,
                    "userImg": img
                   ]

    KeychainWrapper.standard.set(userUid!, forKey: "uid")
    let location =                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Database.database().reference().child("users").child(userUid!).child("pseudo")
    location.setValue(userData)
    dismiss(animated: true, completion: nil)
}

// Upload and put image in the Firebase Storage
func uploadImg() {
    guard let img = userImagePicker.image, imageSelected == true else {
        print("Image needs to be selected")
        return
    }

    if let imgData = UIImageJPEGRepresentation(img, 0.2) {
        let imgUid = NSUUID().uuidString
        let metadata = StorageMetadata()
        metadata.contentType = "image/jpeg"

        Storage.storage().reference().child(imgUid).putData(imgData, metadata: metadata) { (metadata, error) in
            if error != nil {
                print("Did not upload img")
                self.isUploaded = false
            } else {
                print("uploaded")
                self.isUploaded = true
                let downloadURL = metadata?.downloadURL()?.absoluteString
                if let url = downloadURL {
                    self.setUser(img: url)
                }
            }
        }
    }
}

下载方式和下载后显示照片的代码如下:

override func viewDidLoad() {
    super.viewDidLoad()
    imagePicker = UIImagePickerController()
    imagePicker.delegate = self
    imagePicker.allowsEditing = true

    // For download photo from Firebase
    name = Auth.auth().currentUser?.displayName
    userUid = Auth.auth().currentUser?.uid

    refDatabase = Database.database().reference().child("users").child(userUid!)
    refDatabase.child("pseudo").observeSingleEvent(of: .value, with: { (snapshot) in

        if snapshot.hasChild("userImg") {
            self.isUploaded = true
            print("True userImg exists")
            self.downloadPhoto(user: self.name)
        } else {
            self.isUploaded = false
            self.userImagePicker = UIImageView(image: self.photovide)
            self.photoProfil.setImage(self.photovide, for: .normal)
            print("isUploaded2 = false")
            print("false userImg doesn't exist")
            print("Aucune photo n'a été uploadée dans la base de données")
        }
    })
}

override func viewWillAppear(_ animated: Bool) {
    self.userImagePicker.image = nil
    guard let username = Auth.auth().currentUser?.displayName else { return }
    self.navigationItem.title = username

    refDatabase = Database.database().reference().child("users").child(userUid!)

    refDatabase.child("pseudo").observeSingleEvent(of: .value, with: { (snapshot) in

        if snapshot.hasChild("userImg") {
            self.isUploaded = true
            print("isUploaded2 = true")
            print("true userImg exists")
            self.downloadPhoto(user: self.name)
        } else {
            self.isUploaded = false
            self.userImagePicker = UIImageView(image: self.photovide)
            self.photoProfil.setImage(self.photovide, for: .normal)
            print("False userImg doesn't exist")
        }
    })
}

func downloadPhoto(user: String) {
    self.name = user
    let recipientData = Database.database().reference().child("users").child(userUid!).child("pseudo")

    recipientData.observeSingleEvent(of: .value, with: { (snapshot) in
        let data = snapshot.value as! Dictionary<String, AnyObject>
        let nickname = data["nickname"]
        let userImg = data["userImg"]

        let ref = Storage.storage().reference(forURL: userImg! as! String)
        ref.getData(maxSize: 1000000, completion: { (data, error) in
            if error != nil {
                print("Could not load image")
            } else {
                if let imgData = data {
                    if let img = UIImage(data: imgData) {
                        self.userImagePicker.image = img
                        self.photoProfil.setImage(img, for: .normal)
                    }
                }
            }
        })
    })
    userImagePicker.reloadInputViews()
}

func dismissFullscreenImage(_ sender: UITapGestureRecognizer) {
    self.navigationController?.isNavigationBarHidden = false
    self.tabBarController?.tabBar.isHidden = false
    sender.view?.removeFromSuperview()
}

// Try to do the same with the viewDidLoad() method for download but can't work
override func viewDidAppear(_ animated: Bool) {
    refDatabase = Database.database().reference().child("users").child(userUid!)

    refDatabase.child("pseudo").observeSingleEvent(of: .value, with: { (snapshot) in

        if snapshot.hasChild("userImg") {
            self.isUploaded = true
            print("True userImg exists")
            self.downloadPhoto(user: self.name)
        } else {
            self.isUploaded = false
            self.userImagePicker = UIImageView(image: self.photovide)
            self.photoProfil.setImage(self.photovide, for: .normal)
            print("False userImg doesn't exist")
        }
    })
}

您应该尝试在 uploadImg() 方法中调用 downloadPhoto() 方法。

像这样:

func uploadImg() {
    name = Auth.auth().currentUser?.displayName
    userUid = Auth.auth().currentUser?.uid

    guard let img = userImagePicker.image, imageSelected == true else {
        print("Image needs to be selected")
        return
    }

    if let imgData = UIImageJPEGRepresentation(img, 0.2) {
        let imgUid = NSUUID().uuidString
        let metadata = StorageMetadata()
        metadata.contentType = "image/jpeg"

        Storage.storage().reference().child(imgUid).putData(imgData, metadata: metadata) { (metadata, error) in
            if error != nil {
                print("Did not upload img")
                self.isUploaded = false
            } else {
                print("Uploaded")
                self.isUploaded = true
                let downloadURL = metadata?.downloadURL()?.absoluteString
                if let url = downloadURL {
                    self.setUser(img: url)
                    self.downloadPhoto(user: self.name) // Here add it
                }
            }
        }
    }
}

您也可以使用在 viewDidLoad() 和 viewWillAppear() 中使用的一段代码创建一个函数,并在这 2 个方法中调用该函数以获得正确的代码。 希望对你有帮助。