Skip to content

Instantly share code, notes, and snippets.

@pgherveou
Last active November 15, 2015 23:47
Show Gist options
  • Select an option

  • Save pgherveou/c0e5bd639bbdb2b5869c to your computer and use it in GitHub Desktop.

Select an option

Save pgherveou/c0e5bd639bbdb2b5869c to your computer and use it in GitHub Desktop.
First attempt at porting FirebaseArray to swift - https://github.com/firebase/FirebaseUI-iOS
import XCPlayground
import Firebase
import PromiseKit
// MARK: FirebaseArrayDelegate
protocol FirebaseArrayDelegate: class {
func childNotFound(key: String)
func childAdded(snapshot: FDataSnapshot, atIndex index: Int)
func childChanged(snapshot: FDataSnapshot, atIndex index: Int)
func childRemoved(snapshot: FDataSnapshot, atIndex index: Int)
func childMoved(snapshot: FDataSnapshot, fromIndex: Int, toIndex: Int)
}
// MARK: FirebaseArray
class FirebaseArray {
// MARK: properties
weak var delegate: FirebaseArrayDelegate?
// MARK: private properties
private var snapshots: [FDataSnapshot] = []
private let query: FQuery
// MARK: initializers
init(query: FQuery) {
self.query = query
initListeners()
}
// MARK: methods
// MARK: Private methods
private func indexForKey(key: String?) -> Int? {
guard let key = key else { return -1 }
for (index, snapshot) in snapshots.enumerate() where snapshot.key == key { return index }
delegate?.childNotFound(key)
return nil
}
private func initListeners() {
query.observeEventType(.ChildAdded, andPreviousSiblingKeyWithBlock: {(snapshot, previousChildKey) in
guard let previousIndex = self.indexForKey(previousChildKey) else { return }
let index = previousIndex + 1
self.snapshots.insert(snapshot, atIndex: index)
self.delegate?.childAdded(snapshot, atIndex: index)
})
query.observeEventType(.ChildChanged, andPreviousSiblingKeyWithBlock: {(snapshot, previousChildKey) in
guard let index = self.indexForKey(snapshot.key) else { return }
self.snapshots[index] = snapshot
self.delegate?.childChanged(snapshot, atIndex: index)
})
query.observeEventType(.ChildRemoved, withBlock: {(snapshot) in
guard let index = self.indexForKey(snapshot.key) else { return }
self.snapshots.removeAtIndex(index)
self.delegate?.childRemoved(snapshot, atIndex: index)
})
query.observeEventType(.ChildMoved, andPreviousSiblingKeyWithBlock: {(snapshot, previousChildKey) in
guard let fromIndex = self.indexForKey(snapshot.key) else { return }
self.snapshots.removeAtIndex(fromIndex)
guard let previousIndex = self.indexForKey(previousChildKey) else { return }
let toIndex = previousIndex + 1
self.snapshots.insert(snapshot, atIndex: toIndex)
self.delegate?.childMoved(snapshot, fromIndex: fromIndex, toIndex: toIndex)
})
}
}
// MARK: FirebaseArray + CollectionType
extension FirebaseArray: CollectionType {
typealias Index = Int
typealias T = FDataSnapshot
var startIndex: Int {
return 0
}
var endIndex: Int {
return snapshots.count
}
subscript(i: Int) -> T {
return snapshots[i]
}
}
// MARK: Reporter
class Reporter: FirebaseArrayDelegate {
let array: FirebaseArray
init(array: FirebaseArray) {
self.array = array
self.array.delegate = self
}
func childNotFound(key: String) {
print("Key not found: \(key)")
}
func childAdded(snapshot: FDataSnapshot, atIndex index: Int) {
print("\(snapshot.key) added at \(index)")
print(array.map { $0.key })
print("~~~~~")
}
func childChanged(snapshot: FDataSnapshot, atIndex index: Int) {
print("\(snapshot.key) changed to \(index)")
print(array.map { $0.key })
print("~~~~~")
}
func childRemoved(snapshot: FDataSnapshot, atIndex index: Int) {
print("\(snapshot.key) removed at \(index)")
print(array.map { $0.key })
print("~~~~~")
}
func childMoved(snapshot: FDataSnapshot, fromIndex: Int, toIndex: Int) {
print("\(snapshot.key) moved from \(fromIndex) to \(toIndex)")
print(array.map { $0.key })
print("~~~~~")
}
}
// MARK: Demo
func delay(time:Double, closure: () -> Void) {
dispatch_after(
dispatch_time(DISPATCH_TIME_NOW, Int64(time * Double(NSEC_PER_SEC))),
dispatch_get_main_queue(), closure)
}
let ref = Firebase(url: "https://firenext-test2.firebaseio.com/")
ref.removeValue()
let array = FirebaseArray(query: ref.queryOrderedByPriority())
let reporter = Reporter(array: array)
delay(0.1) { ref.childByAppendingPath("a").setValue(true, andPriority: "a") }
delay(0.2) { ref.childByAppendingPath("c").setValue(true, andPriority: "c") }
delay(0.3) { ref.childByAppendingPath("b").setValue(true, andPriority: "b") }
delay(0.4) { ref.childByAppendingPath("c").setPriority("a") }
delay(0.5) { ref.childByAppendingPath("a").removeValue() }
XCPlaygroundPage.currentPage.needsIndefiniteExecution = true
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment