I am working with swift
in Xcode 7
. I am totally new to Swift, Xcode, and Firebase
. I would like to have three UITableViewContro
I do it slightly different when I have a UITableViewController, especially for those that can push to another detail view / or show a modal view over the top.
Having the setObserver in ViewDidAppear works well. However, I didnt like the fact that when I looked into a cells detail view and subsequently popped that view, I was fetching from Firebase and reloading the table again, despite the possibility of no changes being made.
This way the observer is added in viewDidLoad, and is only removed when itself is popped from the Nav Controller stack. The tableview is not reloaded unnecessarily when the viewAppears.
var myRef:FIRDatabaseReference = "" // your reference
override func viewDidLoad() {
super.viewDidLoad()
setObserver()
}
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
// only called when popped from the Nav Controller stack
// if I push to another detail view my observer will remain active
if isBeingDismissed() || isMovingFromParentViewController() {
myRef.removeAllObservers()
}
}
func setObserver() {
myRef.observeEventType(.Value, withBlock: { snapshot in
var newThings = [MyThing]()
for s in snapshot.children {
let ss = s as! FIRDataSnapshot
let new = MyThing(snap: ss) // convert my snapshot into my type
newThings.append(new)
}
self.things = newThings.sort{ $0.name < $1.name) } // some sort
self.tableView.reloadData()
})
}
I also use .ChildChanged
.ChildDeleted
and .ChildAdded
in UITableViews
. They work really well and allow you use UITableView
animations. Its a little more code, but nothing too difficult.
You can use .ChildChanged
to get the initial data one item at a time, then it will monitor for changes after that.
If you want all your data at once in the initial load you will need .Value, I suggest you use observeSingleEventOfType
for your first load of the tableview. Just note that if you also have .ChildAdded
observer you will also get an initial set of data when that observer is added - so you need to deal with those items (i.e. don't add them to your data set) otherwise your items will appear twice on the initial load.
This question is broad, in that it asks how to do three different tasks.
I think you'll be better off getting answers if you only ask for one thing at a time.
I can help you with populating a UITableViewController
with Firebase.
class MyTableViewController: UITableViewController {
// your firebase reference as a property
var ref: Firebase!
// your data source, you can replace this with your own model if you wish
var items = [FDataSnapshot]()
override func viewDidLoad() {
super.viewDidLoad()
// initialize the ref in viewDidLoad
ref = Firebase(url: "<my-firebase-app>/items")
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
// listen for update with the .Value event
ref.observeEventType(.Value) { (snapshot: FDataSnapshot!) in
var newItems = [FDataSnapshot]()
// loop through the children and append them to the new array
for item in snapshot.children {
newItems.append(item as! FDataSnapshot)
}
// replace the old array
self.items = newItems
// reload the UITableView
self.tableView.reloadData()
}
}
}
This technique uses the .Value
event, you can also use .ChildAdded
, but then you have to keep track of .ChildChanged
, '.ChildRemoved', and .ChildMoved
, which can get pretty complicated.
The FirebaseUI library for iOS handles this pretty easily.
dataSource = FirebaseTableViewDataSource(ref: self.firebaseRef, cellReuseIdentifier: "<YOUR-REUSE-IDENTIFIER>", view: self.tableView)
dataSource.populateCellWithBlock { (cell: UITableViewCell, obj: NSObject) -> Void in
let snap = obj as! FDataSnapshot
// Populate cell as you see fit, like as below
cell.textLabel?.text = snap.key as String
}