Skip to content

Instantly share code, notes, and snippets.

@keith-kurak
Last active April 23, 2017 20:48
Show Gist options
  • Save keith-kurak/c725492e2eda9c7bf62e9ea56c125af3 to your computer and use it in GitHub Desktop.
Save keith-kurak/c725492e2eda9c7bf62e9ea56c125af3 to your computer and use it in GitHub Desktop.
Decoupled Firebase code
//1) Have a protocol that serves as a placeholder for something that is observing updates- mainly so you can unsubscribe from updates later when you no longer need them
protocol UpdateObserving {
func unsubscribe()
}
//1a) Implement that protocol for Firebase. It needs a ref that can unsubscribe and a handle to the specific subscription
class FirebaseObserver: UpdateObserving {
private var handle: UInt
private var firebaseReference: FIRDatabaseReference
init(handle: UInt, firebaseRef: FIRDatabaseReference) {
self.handle = handle
self.firebaseReference = firebaseRef
}
func unsubscribe() {
firebaseReference.removeObserver(withHandle: self.handle)
}
}
//2) FirebaseRepository.swift: Have a repository for your Firebase calls. Anything that observes returns an UpdateObserving
func observeRecordChanges(completionBlock: @escaping ([RecordModel]) -> ()) -> UpdateObserving {
let userID = FIRAuth.auth()?.currentUser?.uid
//super-important: you always need a ref to the specific place you're subscribing to. Otherwise you can end up shutting off other subscriptions.
let deepRef = FIRDatabase.database().reference().child("users").child(userID!).child("records")
//keep the return var from your observation
let handle = deepRef.observe(.value, with: {(snapshot) in
var records = [RecordModel]()
for obj in snapshot.children.allObjects as! [FIRDataSnapshot] {
let record = RecordModel(fromSnapshot: obj) //make an object to translate Firebase snapshots into something nice
records.append(record)
}
completionBlock(records)
})
//return the observer when you're done so the consumer can unsubscribe
return FirebaseObserver(handle: handle, firebaseRef: deepRef)
}
//3) TableViewController.swift: subscribe to changes when your VC appears, and unsubscribe when it dissappears.
var records = [RecordModel]()
var recordObserver: UpdateObserving?
var repository = FirebaseRepository()
func viewWillAppear(_ animated: Bool) {
self.recordObserver = self.repository.observeRecordChanges(completionBlock: { [unowned self] (records) in
DispatchQueue.main.async { [unowned self] in
self.records = records
self.tableView.reloadData()
}
}
// don't forget to clean up after yourself or things will get slow or buggy or both //
func viewWillDissappear(_ animated: Bool) {
self.recordObserver?.unsubscribe()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment