我知道有很多的代碼在這裏的SO問題,但它是我能在那一刻做了最好的......你可以複製/粘貼代碼爲一啓動RX-操場上看到的問題。爲什麼完成事件會阻止這個測試通過?
在第89行有一段註釋碼let creds = Observable.just(credentials)//.concat(Observable.never())
。如果我刪除//
並允許concat,代碼將通過它的測試。如果creds
被允許發送完成事件,任何人都可以提供一個線索,說明爲什麼這段代碼不能通過測試?
import Foundation
import RxSwift
import RxCocoa
import UIKit
typealias Credentials = (email: String, password: String)
struct User {
let id: String
let properties: [Property]
}
struct Property {
let id: String
let name: String
}
struct LoginParams {
let touchIDPossible: Bool
}
class LoginScreen {
var attemptLogin: Observable<Credentials> {
assert(_attemptLogin == nil)
_attemptLogin = PublishSubject()
return _attemptLogin!
}
var _attemptLogin: PublishSubject<(email: String, password: String)>?
}
class DashboardScreen {
func display(property: Observable<Property?>) {
property.subscribe(onNext: { [unowned self] in
self._property = $0
}).disposed(by: bag)
}
var _property: Property?
let bag = DisposeBag()
}
class Interface {
func login(params: LoginParams) -> Observable<LoginScreen> {
assert(_login == nil)
_login = PublishSubject()
return _login!
}
func dashboard() -> Observable<DashboardScreen> {
assert(_dashboard == nil)
_dashboard = PublishSubject()
return _dashboard!
}
var _login: PublishSubject<LoginScreen>?
var _dashboard: PublishSubject<DashboardScreen>?
let bag = DisposeBag()
}
class Server {
func user(credentials: Credentials) -> Observable<User> {
assert(_user == nil)
_user = PublishSubject()
return _user!
}
func property(id: String) -> Observable<Property> {
assert(_property == nil)
_property = PublishSubject()
return _property!
}
var _user: PublishSubject<User>?
var _property: PublishSubject<Property>?
}
class Coordinator {
init(interface: Interface, server: Server) {
self.interface = interface
self.server = server
}
func start() {
let credentials = (email: "foo", password: "bar")
// remove the `//` and the test will pass. Why does it fail when `creds` completes?
let creds = Observable.just(credentials)//.concat(Observable.never())
let autoUser = creds.flatMap {
self.server.user(credentials: $0)
.materialize()
.filter { !$0.isCompleted }
}.shareReplayLatestWhileConnected()
let login = autoUser.filter { $0.error != nil }
.flatMap { _ in self.interface.login(params: LoginParams(touchIDPossible: false)) }
let attempt = login.flatMap { $0.attemptLogin }
.shareReplayLatestWhileConnected()
let user = attempt.flatMap {
self.server.user(credentials: $0)
.materialize()
.filter { !$0.isCompleted }
}.shareReplayLatestWhileConnected()
let propertyID = Observable.merge(autoUser, user).map { $0.element }
.filter { $0 != nil }.map { $0! }
.map { $0.properties.sorted(by: { $0.name < $1.name }).map({ $0.id }).first }
let property = propertyID.filter { $0 != nil }.map { $0! }
.flatMap { self.server.property(id: $0)
.map { Optional.some($0) }
.catchErrorJustReturn(nil)
}.debug("property").shareReplayLatestWhileConnected()
let dashboard = property.flatMap { _ in self.interface.dashboard() }
dashboard.map { $0.display(property: property) }
.subscribe()
.disposed(by: bag)
}
let interface: Interface
let server: Server
let bag = DisposeBag()
}
do {
let interface = Interface()
let server = Server()
let coordinator = Coordinator(interface: interface, server: server)
coordinator.start()
assert(server._user != nil)
let simpleProperty = Property(id: "bar", name: "tampa")
let user = User(id: "foo", properties: [simpleProperty])
server._user?.onNext(user)
server._user?.onCompleted()
server._user = nil
assert(interface._login == nil)
assert(server._property != nil)
let property = Property(id: "bar", name: "tampa")
server._property!.onNext(property)
server._property!.onCompleted()
server._property = nil
assert(interface._dashboard != nil)
let dashboard = DashboardScreen()
interface._dashboard?.onNext(dashboard)
interface._dashboard?.onCompleted()
assert(dashboard._property != nil)
print("test passed")
}
這裏是代碼的輸出作爲其高於:
2017-06-01 22:22:42.534: property -> subscribed
2017-06-01 22:22:42.552: property -> Event next(Optional(__lldb_expr_134.Property(id: "bar", name: "tampa")))
2017-06-01 22:22:42.557: property -> Event completed
2017-06-01 22:22:42.557: property -> isDisposed
2017-06-01 22:22:42.559: property -> subscribed
assertion failed: file MyPlayground.playground, line 159
爲什麼property
被訂閱後已經設置?
這裏是輸出,如果你刪除\\
:
2017-06-01 22:23:51.540: property -> subscribed
2017-06-01 22:23:51.553: property -> Event next(Optional(__lldb_expr_136.Property(id: "bar", name: "tampa")))
test passed
既然我們沒有你的行號,你至少可以給代碼添加一個關於哪個斷言失敗的註釋(159行)? – ctietze
對不起,這是最後一次失敗。 –