Извлечение данных из Firebase с помощью URL (Swift)

#ios #swift #url #firebase #firebase-realtime-database

# #iOS #swift #url #firebase #firebase-база данных в реальном времени

Вопрос:

Я создаю приложение, используя серверную часть firebase. У меня есть данные, которые я хотел бы получить. Да, есть опция моментального снимка, но в данном конкретном случае было бы проще получить информацию через URL.

Например, если бы у меня был пользователь в базе данных, и под этим пользователем есть определенный узел с именем messages, а под этим узлом есть много объектов message . Когда вы нажимаете на один из этих узлов в консоли firebase, вы получаете ссылку на верхнюю часть окна (см. Рисунок).

Возможно ли получить информацию из URL-адреса, который находится сверху, и использовать его в качестве моментального снимка для извлечения данных? Я уже видел, как это делалось раньше в более ранних документах firebase, и это именно то, что мне нужно, но оно старое и не работает.

Вот ссылка на этот документ: https://www.firebase.com/docs/ios/guide/retrieving-data.html

Я использую Swift3 и Xcode 8

   // Get a reference to our posts
var ref = Firebase(url:"https://docs-examples.firebaseio.com/web/saving-data/fireblog/posts")

// Attach a closure to read the data at our posts reference
ref.observeEventType(.Value, withBlock: { snapshot in
    println(snapshot.value)
}, withCancelBlock: { error in
    println(error.description)
})
 

Ответ №1:

Как вы видите, Link это краткое изложение .child() параметров "user" и идентификатора пользователя / сообщения, так что:

Что вам нужно сделать, так это сохранить autoID в свой словарь сообщений, чтобы вы могли ссылаться на это и call the message directly . Таким образом, вы « .child() » свой путь к нужному вам сообщению и «косвенно» создаете direct link вместо того, чтобы запрашивать всю вашу Firebase.

Для этого вам необходимо сохранить такие сообщения:

 //for my example I've created a struct: Message
struct Message {
   var message: String = ""
   var user: String = ""
   var messageID: String = ""
}

func saveMessages(userID: String, message: Message) { // or your dictionary

    // here you set an auto id
    let reference = firebase.child(userID).childByAutoId() 

    // here you save the id into your messages dict/model
    message.messageID = reference.key

    // here you save the dict/model into your firebase
    reference.setValue(message) { (error, ref) -> Void in
        if error != nil {
            print("(error)")
        }
    }        
}
 

Вы вызываете функцию с помощью saveMessages(userID: myUserID, messages: message)

Тогда вы либо:

Загрузите все сообщения в массив вашей структуры:

 // we create and instantiate an Array of Message
var messages: [Message] = []

func loadAllMessages(userID: String) {

    //we query all messages from the certain user
    let usersRef = firebase.child(userID).child("messages")
    usersRef.observeEventType(.Value, withBlock: { snapshot in

        if snapshot.exists() {

            // since we use observeEventType we need to clear our Array
            // everytime our snapshot exists so we're not downloading
            // single messages multiple times
            self.messages.removeAll()

            // I'm always sorting for date
            // even if your dict has no date, it doesnt crash
            let sorted = (snapshot.value!.allValues as NSArray).sortedArrayUsingDescriptors([NSSortDescriptor(key: "date",ascending: false)])

            // now we loop through sorted to get every single message
            for element in sorted {

                let message = element.valueForKey("message")! as? String
                let name = element.valueForKey("name")! as? String
                let messageID = element.valueForKey("messageID")! as? String
                // we're creating a message model 
                let m = Message(message: message!, name: name!, messageID: messageID!)
                // and saving it into our array
                self.messages.append(m)                    
            }
        }            
    })
}
 

Или вы вызываете прямой вызов сообщения по идентификатору, который вы (должны) уже знать.

 func loadSingleMessages(userID: String, messageID: String) {

    // we use the direct "link" to our message
    let usersRef = firebase.child(userID).child(messageID)
    usersRef.observeEventType(.Value, withBlock: { snapshot in

        if snapshot.exists() {

            let message = snapshot.valueForKey("message")! as? String
            let name = snapshot.valueForKey("name")! as? String
            let messageID = snapshot.valueForKey("messageID")! as? String           
            // create the model         
            let m = Message(message: message!, name: name!, messageID: messageID!)
            // and save it to our Array    
            self.messages.append(m)                    
        }            
    })
}
 

Резюме: чтобы иметь возможность напрямую вызывать ваше сообщение без необходимости запрашивать всю Firebase и перебирать путь к нужному сообщению, вам необходимо знать сгенерированное autoID , сохранить его и запросить ссылку с этим идентификатором.

Вы могли бы, например, настроить массив внутри вашего пользователя в Firebase, хранящий только идентификаторы сообщений. И затем вы можете использовать их для запроса нужных сообщений.

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

 struct User {
   var userID: String = ""
   var name: String = ""
   var email: String = ""
   var profileImageURL = ""
   var messages: [String] = []
}

let user = User()
 

После того, как вы загрузили и создали экземпляр своей пользовательской модели из Firebase, вы:

 // for every message in our user.messages we call our function
for message in user.messages { 
    loadSingleMessages(userID: user.userID, messageID: message)
}
 

Кстати, MessageId также важен для возможности удаления или редактирования определенного сообщения.

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

1. Большое вам спасибо за этот подробный ответ. Я попробую это сегодня и отчитаюсь перед вами!