Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Firebase converting snapshot value to objects

So I have a postDict as [String: AnyObject] and I have a model class Post.

Is there a quick way to convert postDict to an array of Post objects so that when dequeuing the cell, it will be:

cell.textLabel.text = posts[indexPath.item].author

import UIKit
import Firebase

class ViewController: UIViewController {

var posts = [Post]()

override func viewDidLoad() {
    super.viewDidLoad()

    let ref = FIRDatabase.database().reference().child("posts").queryLimitedToFirst(5)

    ref.observeEventType(FIRDataEventType.ChildAdded, withBlock: { (snapshot) in
        let postDict = snapshot.value as! [String : AnyObject]

        print(postDict)          

        //convert postDict to array of Post objects
    })
  }
}

class Post: NSObject {
    var author: String = ""
    var body: String = ""
    var imageURL: String = ""
    var uid: String = ""
}

This is the output when printing out postDict:

enter image description here

like image 660
Daryl Wong Avatar asked Jun 26 '16 13:06

Daryl Wong


1 Answers

Try using the class, protocol and extension I have created below, it will save you a lot of time trying to map the snapshots to objects.

//
//  FIRDataObject.swift
//
//  Created by Callam Poynter on 24/06/2016.
//

import Firebase

class FIRDataObject: NSObject {

    let snapshot: FIRDataSnapshot
    var key: String { return snapshot.key }
    var ref: FIRDatabaseReference { return snapshot.ref }

    required init(snapshot: FIRDataSnapshot) {

        self.snapshot = snapshot

        super.init()

        for child in in snapshot.children.allObjects as? [FIRDataSnapshot] ?? [] {
            if respondsToSelector(Selector(child.key)) {
                setValue(child.value, forKey: child.key)
            }
        }
    }
}

protocol FIRDatabaseReferenceable {
    var ref: FIRDatabaseReference { get }
}

extension FIRDatabaseReferenceable {
    var ref: FIRDatabaseReference {
        return FIRDatabase.database().reference()
    }
}

Now you can create a model that inherits the FIRDataObject class and can be initialised with a FIRDataSnapshot. Then add the FIRDatabaseReferenceable protocol to your ViewController to get access to your base reference.

import Firebase
import UIKit

class ViewController: UIViewController, FIRDatabaseReferenceable {

    var posts: [Post] = []

    override func viewDidLoad() {

        super.viewDidLoad()

        ref.child("posts").observeEventType(.ChildAdded, withBlock: {
            self.posts.append(Post(snapshot: $0))
        })
    }
}

class Post: FIRDataObject {

    var author: String = ""
    var body: String = ""
    var imageURL: String = ""
}

UPDATE for Swift 3

class FIRDataObject: NSObject {

    let snapshot: FIRDataSnapshot
    var key: String { return snapshot.key }
    var ref: FIRDatabaseReference { return snapshot.ref }

    required init(snapshot: FIRDataSnapshot) {

        self.snapshot = snapshot

        super.init()

        for child in snapshot.children.allObjects as? [FIRDataSnapshot] ?? [] {
            if responds(to: Selector(child.key)) {
                setValue(child.value, forKey: child.key)
            }
        }
    }
}
like image 98
Callam Avatar answered Sep 21 '22 18:09

Callam