Как сгруппировать массив URL-адресов изображений вместе в базе данных Firebase Realtime? (Swift)

#swift #database #firebase #firebase-realtime-database

#swift #База данных #firebase #firebase-realtime-database

Вопрос:

У меня есть следующий код:

 @IBAction func postFinalButton(_ sender: Any) {
        while index < ImagesOnClick.count {
            ProgressHUD.show()
            ProgressHUD.animationType = .circleRotateChase
            ProgressHUD.colorAnimation = #colorLiteral(red: 0.337254902, green: 0.6156862745, blue: 0.9803921569, alpha: 1)
            ProgressHUD.colorHUD = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)
        guard let imageSelected = ImagesOnClick[index] else {
            print("Image is nil")
            return
        }
        index  = 1
        guard let imageData = imageSelected.jpegData(compressionQuality: 0.4) else {
            print("This is nil")
            return
        }
        let storageRef = Storage.storage().reference(forURL: "gs://loginpage-227bd.appspot.com")
        let storageRefPosts = storageRef.child("posts").child(Auth.auth().currentUser!.uid)
        let metadata = StorageMetadata()
        metadata.contentType = "image/jpg"
        storageRefPosts.putData(imageData, metadata: metadata, completion: {
            (storageMetaData, error) in
            if error != nil {
                
                print("error")
                return
            }
            print("blala")
            storageRefPosts.downloadURL(completion: { (url, error) in
                if let metaImageUrl = url?.absoluteString {
                    print(metaImageUrl)
                    self.sendDataToDatabase(photoUrl: metaImageUrl)
                    //self.performSegue(withIdentifier: "BackToHome", sender: self)
                }
            })
        })
        }
    }
    func sendDataToDatabase(photoUrl: String) {
        let ref = Database.database().reference()
        let postsRefrence = ref.child("posts")
        let newPostId = postsRefrence.childByAutoId().key
        let newPostsRefrence = postsRefrence.child(newPostId!)
        newPostsRefrence.setValue(["photoUrl": photoUrl], withCompletionBlock: {
            (error, ref) in
            if error != nil {
                ProgressHUD.showError(error?.localizedDescription)
                return
            }
            ProgressHUD.showSucceed()
        })
    }
  

Тогда моя модель выглядит так:

Изображение

Если вы посмотрите на базу данных, вы увидите 4 разных изображения, каждое из которых имеет отдельный идентификатор. Проблема в том, что я загрузил все эти изображения одновременно. Я пытаюсь создать приложение, в котором вы можете публиковать изображения, а затем просматривать их. Однако, если я загружаю несколько изображений вместе, они сохраняются как совершенно отдельные изображения. Я хочу, чтобы пользователь загружал массив изображений, которые они хранят вместе, чтобы я мог получить их как одно сообщение. Мой вопрос в том, как мне это сделать?

Редактировать

Я изменил свой код на:

 @IBAction func postFinalButton(_ sender: Any) {
        let ref = Database.database().reference()
        let postsReference = ref.child("posts")
        let newImagesRef = postsReference.childByAutoId()
        while index < ImagesOnClick.count {
            ProgressHUD.show()
            ProgressHUD.animationType = .circleRotateChase
            ProgressHUD.colorAnimation = #colorLiteral(red: 0.337254902, green: 0.6156862745, blue: 0.9803921569, alpha: 1)
            ProgressHUD.colorHUD = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)
        guard let imageSelected = ImagesOnClick[index] else {
            print("Image is nil")
            return
        }
        index  = 1
        guard let imageData = imageSelected.jpegData(compressionQuality: 0.4) else {
            print("This is nil")
            return
        }
        let storageRef = Storage.storage().reference(forURL: "gs://loginpage-227bd.appspot.com")
        let storageRefPosts = storageRef.child("posts").child(Auth.auth().currentUser!.uid)
        let metadata = StorageMetadata()
        metadata.contentType = "image/jpg"
        storageRefPosts.putData(imageData, metadata: metadata, completion: {
            (storageMetaData, error) in
            if error != nil {
                
                print("error")
                return
            }
            print("blala")
            storageRefPosts.downloadURL(completion: { (url, error) in
                if let metaImageUrl = url?.absoluteString {
                    print(metaImageUrl)
                    self.sendDataToDatabase(photoUrl: metaImageUrl, ref: postsReference, index: self.index)
                    //self.performSegue(withIdentifier: "BackToHome", sender: self)
                }
            })
        })
        }
    }
    func sendDataToDatabase(photoUrl: String, ref: DatabaseReference, index: Int) {
        let name = "photoUrl" String(index)
        ref.setValue([name: photoUrl], withCompletionBlock: {
            (error, ref) in
            if error != nil {
                ProgressHUD.showError(error?.localizedDescription)
                return
            }
            ProgressHUD.showSucceed()
        })
    }
  

Но теперь, когда я нажимаю кнопку post, сохраняется только последний выбранный URL-адрес изображения, и вместо того, чтобы каждое сообщение сохранялось под новым идентификатором, они сохраняются под дочерним элементом posts. Вот изображение того, как это выглядит:

Изображение базы данных

Ответ №1:

Каждый раз, когда вы вызываете childByAutoId() его, создается новое уникальное местоположение в базе данных. Поскольку теперь вы вызываете childByAutoId() каждое изображение, каждое изображение сохраняется под своим собственным идентификатором auto ID.

Хитрость заключается в том, чтобы вызывать только childByAutoId() один раз для всех изображений. Но это означает, что вам нужно будет использовать другое уникальное имя свойства для каждого изображения, поскольку все они не могут быть вызваны photoUrl (ключи должны быть уникальными в их родительском узле).

Один из способов сделать это:

  1. Вызовите childByAutoId() один раз в postFinalButton методе и передайте полученный ключ в sendDataToDatabase .
  2. Используйте индекс каждого файла как часть его имени файла, также передавая это значение в sendDataToDatabase .

Что-то вроде этого в postFinalButton :

 let ref = Database.database().reference()
let postsReference = ref.child("posts")
let newImagesRef = postsRefrence.childByAutoId()

...

storageRefPosts.putData(imageData, metadata: metadata, completion: {
    (storageMetaData, error) in
    if error != nil {            
        print("error")
        return
    }
    storageRefPosts.downloadURL(completion: { (url, error) in
        if let metaImageUrl = url?.absoluteString {
            self.sendDataToDatabase(photoUrl: metaImageUrl, newImagesRef, index)
        }
    })
})
  

И затем:

 func sendDataToDatabase(photoUrl: String, ref: DatabaseReference, index: int) {
    let name = "photoUrl" String(index)
    ref.setValue([name: photoUrl], withCompletionBlock: {
        (error, ref) in
        if error != nil {
            ProgressHUD.showError(error?.localizedDescription)
            return
        }
        ProgressHUD.showSucceed()
    })
}
  

Комментарии:

1. Пожалуйста, посмотрите мое редактирование, кстати, я только что понял, почему для каждого сообщения не был создан новый идентификатор, но у меня все еще возникают проблемы с отображением только конечного URL-адреса изображения, а не всех из них. Например, если есть 4 изображения, и я отправляюсь их публиковать, я увижу только photoURL4: в базе данных.

2. Ах, я передавал неправильную ссылку sendDataToDatabase . Сейчас я обновил код в своем ответе, но надеялся, что вы сможете устранить подобные незначительные ошибки, основываясь на объяснении, которое я дал о том, как работает процесс.

3. Это была не проблема, с которой я столкнулся, проблема в том, что независимо от того, что я делаю, в childbyautoid сохраняется только один ImageUrl