如何按顺序执行操作并更新 UI
How can execute operations sequentially and update UI
我正在尝试按顺序执行一系列操作,并在每次操作开始和结束时更新我的 UI(我必须更新操作状态图标颜色)。
在我的(工作)代码下方:
class SyncManager {
private let disposeBag = DisposeBag()
// MARK: - Private Init
private init() { }
// MARK: - Public Constants
static let shared = SyncManager()
let refreshTokenStatus = BehaviorRelay<SyncStatus>(value: .todo)
let updateCatalogDataStatus = BehaviorRelay<SyncStatus>(value: .todo)
let insertDataStatus = BehaviorRelay<SyncStatus>(value: .todo)
let getDataStatus = BehaviorRelay<SyncStatus>(value: .todo)
func startDatabaseSync(completion: @escaping ((Result<Void, Error>) -> Void)) {
refreshTokenStatus.accept(.todo)
updateCatalogDataStatus.accept(.todo)
insertDataStatus.accept(.todo)
getDataStatus.accept(.todo)
RefreshTokenManager.shared.refreshToken().do(onSuccess: { [self]_ in
print("RefreshTokenManager onSuccess")
refreshTokenStatus.accept(.completed)
}, onError: { [self] error in
print("RefreshTokenManager onError: \(error)")
refreshTokenStatus.accept(.error)
}, onSubscribe: { [self] in
print("RefreshTokenManager onSubscribe")
refreshTokenStatus.accept(.running)
}).asObservable().concatMap { result in
UpdateCatalogDataSyncManager.shared.updateCatalogData().do(onSuccess: { [self] in
print("UpdateCatalogDataSyncManager onSuccess")
updateCatalogDataStatus.accept(.completed)
}, onError: { [self] error in
print("UpdateCatalogDataSyncManager onError: \(error)")
updateCatalogDataStatus.accept(.error)
}, onSubscribe: { [self] in
print("UpdateCatalogDataSyncManager onSubscribe")
updateCatalogDataStatus.accept(.running)
}).asObservable().concatMap { result in
GetDataSyncManager.shared.getData().do { [self] in
print("GetDataSyncManager onSuccess")
getDataStatus.accept(.completed)
} onError: { [self] error in
print("GetDataSyncManager onError: \(error)")
getDataStatus.accept(.error)
} onSubscribe: { [self] in
print("GetDataSyncManager onSubscribe")
getDataStatus.accept(.running)
} onDispose: {
print("GetDataSyncManager onDispose")
}.asObservable().concatMap { _ in
InsertDataWorkSyncManager.shared.insertData().do { [self] in
print("InsertDataWorkSyncManager onSuccess")
insertDataStatus.accept(.completed)
} onError: { [self] error in
print("InsertDataWorkSyncManager onError: \(error)")
insertDataStatus.accept(.error)
} onSubscribe: { [self] in
print("InsertDataWorkSyncManager onSubscribe")
insertDataStatus.accept(.running)
} onDispose: {
print("InsertDataWorkSyncManager onDispose")
}
}
}
}.subscribe { _ in
print("SyncManager onNext")
} onError: { error in
print("SyncManager onError: \(error)")
completion(.failure(error))
} onCompleted: {
print("SyncManager onCompleted")
completion(.success(()))
} onDisposed: {
print("SyncManager onDisposed")
}.disposed(by: disposeBag)
}
}
enum SyncStatus {
case todo
case completed
case error
case running
case partial
}
我的ViewController
:
SyncManager.shared.refreshTokenStatus.skip(1).subscribe(onNext: { status in
// Update UI
}).disposed(by: disposeBag)
SyncManager.shared.updateCatalogDataStatus.skip(1).subscribe(onNext: { status in
// Update UI
}).disposed(by: disposeBag)
SyncManager.shared.insertDataStatus.skip(1).subscribe(onNext: { status in
// Update UI
}).disposed(by: disposeBag)
我是RxSwift
的新手(我只用了一个星期)所以我想知道是否有更好的方法来实现我的上述目标。
这是一个我认为可行的想法。它在概念上非常重要,这使得很难转录到 FRP 的功能声明范式。我保留了相同的外部接口,因此它可以作为替代品。
class SyncManager {
private init() { }
static let shared = SyncManager()
let refreshTokenStatus = BehaviorRelay<SyncStatus>(value: .todo)
let updateCatalogDataStatus = BehaviorRelay<SyncStatus>(value: .todo)
let insertDataStatus = BehaviorRelay<SyncStatus>(value: .todo)
let getDataStatus = BehaviorRelay<SyncStatus>(value: .todo)
private let disposeBag = DisposeBag()
func startDatabaseSync(completion: @escaping (Result<Void, Error>) -> Void) {
let sync = Sync.startDatabaseSync()
disposeBag.insert(
sync.refreshTokenStatus.bind(to: refreshTokenStatus),
sync.updateCatalogDataStatus.bind(to: updateCatalogDataStatus),
sync.insertDataStatus.bind(to: insertDataStatus),
sync.getDataStatus.bind(to: getDataStatus),
sync.getDataStatus.subscribe(
onError: { error in
completion(.failure(error))
},
onCompleted: {
completion(.success(()))
}
)
)
}
}
struct Sync {
let refreshTokenStatus: Observable<SyncStatus>
let updateCatalogDataStatus: Observable<SyncStatus>
let getDataStatus: Observable<SyncStatus>
let insertDataStatus: Observable<SyncStatus>
static func startDatabaseSync() -> Sync {
let refreshTokenStatus = handle(RefreshTokenManager.shared.refreshToken(), after: .just(.completed))
.catchAndReturn(.error)
let updateCatalogDataStatus = handle(UpdateCatalogDataSyncManager.shared.updateCatalogData(), after: refreshTokenStatus)
.catchAndReturn(.error)
let getDataStatus = handle(GetDataSyncManager.shared.getData(), after: updateCatalogDataStatus)
.catchAndReturn(.error)
let insertDataStatus = handle(InsertDataWorkSyncManager.shared.insertData(), after: getDataStatus)
.catchAndReturn(.error)
return Sync(
refreshTokenStatus: refreshTokenStatus,
updateCatalogDataStatus: updateCatalogDataStatus,
getDataStatus: getDataStatus,
insertDataStatus: insertDataStatus
)
}
}
func handle(_ operation: Single<Void>, after: Observable<SyncStatus>) -> Observable<SyncStatus> {
after
.ignoreElements()
.asCompletable()
.andThen(
operation
.map { SyncStatus.completed }
.asObservable()
.startWith(SyncStatus.running)
)
.startWith(.todo)
}
enum SyncStatus {
case todo
case completed
case error
case running
}
如果您重新安排其余代码,使之更符合 Rx 风格,那么您可能会使代码更简洁...
我正在尝试按顺序执行一系列操作,并在每次操作开始和结束时更新我的 UI(我必须更新操作状态图标颜色)。
在我的(工作)代码下方:
class SyncManager {
private let disposeBag = DisposeBag()
// MARK: - Private Init
private init() { }
// MARK: - Public Constants
static let shared = SyncManager()
let refreshTokenStatus = BehaviorRelay<SyncStatus>(value: .todo)
let updateCatalogDataStatus = BehaviorRelay<SyncStatus>(value: .todo)
let insertDataStatus = BehaviorRelay<SyncStatus>(value: .todo)
let getDataStatus = BehaviorRelay<SyncStatus>(value: .todo)
func startDatabaseSync(completion: @escaping ((Result<Void, Error>) -> Void)) {
refreshTokenStatus.accept(.todo)
updateCatalogDataStatus.accept(.todo)
insertDataStatus.accept(.todo)
getDataStatus.accept(.todo)
RefreshTokenManager.shared.refreshToken().do(onSuccess: { [self]_ in
print("RefreshTokenManager onSuccess")
refreshTokenStatus.accept(.completed)
}, onError: { [self] error in
print("RefreshTokenManager onError: \(error)")
refreshTokenStatus.accept(.error)
}, onSubscribe: { [self] in
print("RefreshTokenManager onSubscribe")
refreshTokenStatus.accept(.running)
}).asObservable().concatMap { result in
UpdateCatalogDataSyncManager.shared.updateCatalogData().do(onSuccess: { [self] in
print("UpdateCatalogDataSyncManager onSuccess")
updateCatalogDataStatus.accept(.completed)
}, onError: { [self] error in
print("UpdateCatalogDataSyncManager onError: \(error)")
updateCatalogDataStatus.accept(.error)
}, onSubscribe: { [self] in
print("UpdateCatalogDataSyncManager onSubscribe")
updateCatalogDataStatus.accept(.running)
}).asObservable().concatMap { result in
GetDataSyncManager.shared.getData().do { [self] in
print("GetDataSyncManager onSuccess")
getDataStatus.accept(.completed)
} onError: { [self] error in
print("GetDataSyncManager onError: \(error)")
getDataStatus.accept(.error)
} onSubscribe: { [self] in
print("GetDataSyncManager onSubscribe")
getDataStatus.accept(.running)
} onDispose: {
print("GetDataSyncManager onDispose")
}.asObservable().concatMap { _ in
InsertDataWorkSyncManager.shared.insertData().do { [self] in
print("InsertDataWorkSyncManager onSuccess")
insertDataStatus.accept(.completed)
} onError: { [self] error in
print("InsertDataWorkSyncManager onError: \(error)")
insertDataStatus.accept(.error)
} onSubscribe: { [self] in
print("InsertDataWorkSyncManager onSubscribe")
insertDataStatus.accept(.running)
} onDispose: {
print("InsertDataWorkSyncManager onDispose")
}
}
}
}.subscribe { _ in
print("SyncManager onNext")
} onError: { error in
print("SyncManager onError: \(error)")
completion(.failure(error))
} onCompleted: {
print("SyncManager onCompleted")
completion(.success(()))
} onDisposed: {
print("SyncManager onDisposed")
}.disposed(by: disposeBag)
}
}
enum SyncStatus {
case todo
case completed
case error
case running
case partial
}
我的ViewController
:
SyncManager.shared.refreshTokenStatus.skip(1).subscribe(onNext: { status in
// Update UI
}).disposed(by: disposeBag)
SyncManager.shared.updateCatalogDataStatus.skip(1).subscribe(onNext: { status in
// Update UI
}).disposed(by: disposeBag)
SyncManager.shared.insertDataStatus.skip(1).subscribe(onNext: { status in
// Update UI
}).disposed(by: disposeBag)
我是RxSwift
的新手(我只用了一个星期)所以我想知道是否有更好的方法来实现我的上述目标。
这是一个我认为可行的想法。它在概念上非常重要,这使得很难转录到 FRP 的功能声明范式。我保留了相同的外部接口,因此它可以作为替代品。
class SyncManager {
private init() { }
static let shared = SyncManager()
let refreshTokenStatus = BehaviorRelay<SyncStatus>(value: .todo)
let updateCatalogDataStatus = BehaviorRelay<SyncStatus>(value: .todo)
let insertDataStatus = BehaviorRelay<SyncStatus>(value: .todo)
let getDataStatus = BehaviorRelay<SyncStatus>(value: .todo)
private let disposeBag = DisposeBag()
func startDatabaseSync(completion: @escaping (Result<Void, Error>) -> Void) {
let sync = Sync.startDatabaseSync()
disposeBag.insert(
sync.refreshTokenStatus.bind(to: refreshTokenStatus),
sync.updateCatalogDataStatus.bind(to: updateCatalogDataStatus),
sync.insertDataStatus.bind(to: insertDataStatus),
sync.getDataStatus.bind(to: getDataStatus),
sync.getDataStatus.subscribe(
onError: { error in
completion(.failure(error))
},
onCompleted: {
completion(.success(()))
}
)
)
}
}
struct Sync {
let refreshTokenStatus: Observable<SyncStatus>
let updateCatalogDataStatus: Observable<SyncStatus>
let getDataStatus: Observable<SyncStatus>
let insertDataStatus: Observable<SyncStatus>
static func startDatabaseSync() -> Sync {
let refreshTokenStatus = handle(RefreshTokenManager.shared.refreshToken(), after: .just(.completed))
.catchAndReturn(.error)
let updateCatalogDataStatus = handle(UpdateCatalogDataSyncManager.shared.updateCatalogData(), after: refreshTokenStatus)
.catchAndReturn(.error)
let getDataStatus = handle(GetDataSyncManager.shared.getData(), after: updateCatalogDataStatus)
.catchAndReturn(.error)
let insertDataStatus = handle(InsertDataWorkSyncManager.shared.insertData(), after: getDataStatus)
.catchAndReturn(.error)
return Sync(
refreshTokenStatus: refreshTokenStatus,
updateCatalogDataStatus: updateCatalogDataStatus,
getDataStatus: getDataStatus,
insertDataStatus: insertDataStatus
)
}
}
func handle(_ operation: Single<Void>, after: Observable<SyncStatus>) -> Observable<SyncStatus> {
after
.ignoreElements()
.asCompletable()
.andThen(
operation
.map { SyncStatus.completed }
.asObservable()
.startWith(SyncStatus.running)
)
.startWith(.todo)
}
enum SyncStatus {
case todo
case completed
case error
case running
}
如果您重新安排其余代码,使之更符合 Rx 风格,那么您可能会使代码更简洁...