Skip to content

Instantly share code, notes, and snippets.

@bpyamasinn
Created December 25, 2017 05:36
Show Gist options
  • Save bpyamasinn/138a6e8264cf181bbf01e2cb162bf73e to your computer and use it in GitHub Desktop.
Save bpyamasinn/138a6e8264cf181bbf01e2cb162bf73e to your computer and use it in GitHub Desktop.
import UIKit
import RxSwift
import FirebaseFirestore
class ViewController: UIViewController {
@IBOutlet weak var tableView: UITableView!
var posts = [Post]()
let disposeBag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
Firestore.firestore().collection("posts").addSnapshotListener { [unowned self] (snapshot, error) in
guard let snapshot = snapshot else { return }
var posts = snapshot.documents.map {
try! Post(key: $0.documentID, dictionary: $0.data())
}
let observables: [Observable<User>] = posts.map {
self.observeUser(documentRef: $0.userReference)
}
Observable.zip(observables).subscribe({
guard let users = $0.element else { return }
for user in users {
for (index, post) in posts.enumerated() where post.userReference.documentID == user.id {
posts[index].userEntity = user
}
}
self.posts = posts
self.tableView.reloadData()
}).disposed(by: self.disposeBag)
}
}
fileprivate func observeUser(documentRef: DocumentReference) -> Observable<User> {
return Observable.create { observer in
documentRef.addSnapshotListener { snapshot, error in
guard let snapshot = snapshot else {
observer.on(.error(error!))
return
}
do {
observer.on(.next(try User(key: snapshot.documentID, dictionary: snapshot.data())))
} catch {
observer.on(.error(error))
}
}
return Disposables.create()
}
}
}
extension ViewController: UITableViewDelegate, UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return posts.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: .value2, reuseIdentifier: nil)
cell.textLabel?.text = posts[indexPath.row].userEntity?.name
cell.detailTextLabel?.text = posts[indexPath.row].title
return cell
}
}
struct Post {
let id: String
let title: String
let userReference: DocumentReference
var userEntity: User?
init(key: String, dictionary: [String: Any]) throws {
guard let title = dictionary["title"] as? String,
let userReference = dictionary["userReference"] as? DocumentReference else { throw FirestoreError.initializeFailed }
self.id = key
self.title = title
self.userReference = userReference
}
}
struct User {
let id: String
let name: String
init(key: String, dictionary: [String: Any]) throws {
guard let name = dictionary["name"] as? String else { throw FirestoreError.initializeFailed }
self.id = key
self.name = name
}
}
enum FirestoreError: Error {
case initializeFailed
var localizedDescription: String {
switch self {
case .initializeFailed:
return "error"
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment