简体   繁体   中英

Fetching Data from Firebase with URL (Swift)

I am making an app using a firebase backend. I have data stored I would like to get out. Yes, there is the snapshot option, but in this specific case, it would be easier to get the information through a URL.

For example, If I had a user in the database, and under that user, there is a specific node named messages and under that node, there are many message objects. When you click on one of these nodes in the firebase console, you get a reference to the top of the box ( see picture ).

Is it possible to get information from the URL that's on the top and use it as a snapshot to retrieve data? I've have seen it done before on the earlier firebase docs and it's exactly what I need, but it's old and doesn't work.

Here is the link to that doc: https://www.firebase.com/docs/ios/guide/retrieving-data.html

I am using Swift3 and 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)
})

As you see, your Link is a summary of the .child() parameters "user" and the ID of the User/Message, so:

What you need to do is, to save the autoID into your messages dictionary, so you can reference to that and call the message directly . That way you " .child() " your way to the message that you need and "indirectly" create a direct link instead of querying your whole Firebase.

For that purpose you need to save the Messages like that:

//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)")
        }
    }        
}

You call the function by saveMessages(userID: myUserID, messages: message)

Then you either:

Load all the messages into an Array of your struct:

// 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)                    
            }
        }            
    })
}

Or you call directly call the Message by the ID you (need to) already know.

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)                    
        }            
    })
}

Summary : to be able to call directly your message without having to query through the whole Firebase and to have to loop your way to the desired message, you need to know the generated autoID , store that and query for the reference with that ID.

You could for example set up an Array inside your User at the Firebase storing just the messageIDs. And then you could use those to query for the messages you want.

Something like this:

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

let user = User()

After you have then downloaded and instantiated your User model from your Firebase, you:

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

By the way, the messageID is also important to be able to delete or edit a certain message.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM