swift 公司的FireStoreのRxSwiftとの组み合わせ.Codableも活用。
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了swift 公司的FireStoreのRxSwiftとの组み合わせ.Codableも活用。相关的知识,希望对你有一定的参考价值。
func update(user: User, parameters: UsersRequests.ProfileUpdateParameters) -> Single<()> {
return self.apiClient.response(UsersRequests.Update(userId: user.id,
parameters: parameters))
.flatMap { response in
return Firestore.firestore().rx.setData(User.self,
documentRef: user.makeDocumentRef(),
fields: response.asDictionary(containsId: false))
}
}
Firestore.firestore().rx
.observe(User.self,
documentRef: user.makeDocumentRef())
.subscribe { [unowned self] (event: Event<User>) in
switch event {
case .completed: break
case .error(let error): logger.error(error)
case .next(let user):
self.user = user
guard let profile = user.fields?.profile else { return }
self.userNameLabel.text = profile.name
self.userImageView.set(imageUrl: profile.imageUrl, rounded: true)
}
}
.disposed(by: rx.disposeBag)
public struct User: DatabaseCollection {
public static let collectionName = "users"
public let id: String
public let fields: Fields?
public struct Fields: Codable {
public let profile: Profile
}
public struct Profile: Codable {
public let name: String
public let imageUrl: URL
public let birthday: Date
public let gender: Gender
}
public init(id: String, fields: Fields?) {
self.id = id
self.fields = fields
}
}
import Foundation
import Lib
import FirebaseFirestore
public protocol DatabaseCollection {
associatedtype FieldType: Codable
static var collectionName: String { get }
var id: String { get }
var fields: FieldType? { get }
init(id: String, fields: FieldType?)
init(id: String, json: [String: Any]) throws
static func makeCollectionRef() -> CollectionReference
static func makeDocumentRef(id: String) -> DocumentReference
func makeDocumentRef() -> DocumentReference
}
extension DatabaseCollection {
public init(id: String) {
self.init(id: id, fields: nil)
}
public init(id: String, json: [String: Any]) {
// TODO: If performance is prioritized, map by hand
do {
let data = try JSONSerialization.data(withJSONObject: json)
let decoded = try JSONDecoder.ghost.decode(FieldType.self, from: data)
self.init(id: id, fields: decoded)
} catch {
logger.error(error)
self.init(id: id)
}
}
public static func makeCollectionRef() -> CollectionReference { return Firestore.firestore().collection(collectionName) }
public static func makeDocumentRef(id: String) -> DocumentReference { return Self.makeCollectionRef().document(id) }
public func makeDocumentRef() -> DocumentReference { return Self.makeDocumentRef(id: id) }
}
//
// Database.swift
// Model
//
// Created by mono on 2017/10/14.
// Copyright © 2017 Masayuki Ono All rights reserved.
//
import Foundation
import FirebaseCore
import FirebaseFirestore
import RxSwift
import Lib
import Api
extension Reactive where Base: Firestore {
public func setData<T: DatabaseCollection>(_ type: T.Type,
documentRef: DocumentReference,
fields: [String: Any]) -> Single<()> {
return Single.create { observer in
documentRef
.setData(fields) { error in
if let error = error {
logger.error(error)
observer(.error(error))
} else {
observer(.success(()))
}
}
return Disposables.create()
}
}
public func updateData<T: DatabaseCollection>(_ type: T.Type,
documentRef: DocumentReference,
fields: [String: Any]) -> Single<()> {
return Single.create { observer in
documentRef
.updateData(fields) { error in
if let error = error {
logger.error(error)
observer(.error(error))
} else {
observer(.success(()))
}
}
return Disposables.create()
}
}
public func get<T: DatabaseCollection>(_ type: T.Type,
documentRef: DocumentReference) -> Single<T> {
return Single.create { observer in
documentRef
.getDocument { snapshot, error in
if let error = error {
observer(.error(error))
return
}
guard let snapshot = snapshot else {
observer(.error(ApplicationError.unknown))
return
}
do {
observer(.success(try snapshot.makeResult(id: snapshot.documentID)))
} catch {
logger.error(error)
observer(.error(error))
}
}
return Disposables.create()
}
}
func get<T: DatabaseCollection>(_ type: T.Type,
collectionRef: CollectionReference) -> Single<[T]> {
return Single.create { observer in
collectionRef
.getDocuments { snapshot, error in
if let error = error {
observer(.error(error))
return
}
guard let snapshot = snapshot else {
observer(.error(ApplicationError.unknown))
return
}
let results = snapshot.documents.flatMap { snapshot -> T? in
do {
return try snapshot.makeResult(id: snapshot.documentID)
} catch {
// TODO: error handling
logger.error(error)
return nil
}
}
observer(.success(results))
}
return Disposables.create()
}
}
public func observe<T: DatabaseCollection>(_ type: T.Type,
documentRef: DocumentReference) -> Observable<T> {
return Observable.create { observer in
documentRef
.addSnapshotListener { snapshot, error in
if let error = error {
observer.on(.error(error))
return
}
guard let snapshot = snapshot else {
observer.on(.error(ApplicationError.unknown))
return
}
do {
observer.on(.next(try snapshot.makeResult(id: snapshot.documentID)))
} catch {
logger.error(error)
observer.on(.error(error))
}
}
return Disposables.create()
}
}
public func observe<T: DatabaseCollection>(_ type: T.Type,
collectionRef: CollectionReference) -> Observable<[T]> {
return Observable.create { observer in
collectionRef
.addSnapshotListener { snapshot, error in
if let error = error {
observer.on(.error(error))
return
}
guard let snapshot = snapshot else {
observer.on(.error(ApplicationError.unknown))
return
}
// TODO: ここでは全件返しているが、RxRealmのようにchangesetメソッドも欲しい https://github.com/RxSwiftCommunity/RxRealm
let results = snapshot.documents.flatMap { snapshot -> T? in
do {
return try snapshot.makeResult(id: snapshot.documentID)
} catch {
// TODO: error handling
logger.error(error)
return nil
}
}
observer.on(.next(results))
}
return Disposables.create()
}
}
}
extension DocumentSnapshot {
func makeResult<T: DatabaseCollection>(id: String) throws -> T {
guard exists else {
throw ApplicationError.notFoundEntity(documentId: documentID)
}
let json = data()
logger.debug(json)
return try T(id: id, json: json)
}
}
以上是关于swift 公司的FireStoreのRxSwiftとの组み合わせ.Codableも活用。的主要内容,如果未能解决你的问题,请参考以下文章