A second issue showed up with replaceError(with:) in a more complicated piece of code.
extension ObservableConvertibleType {
/// Returns a `AnyPublisher` of the underlying Observable's Element type
/// so the Observable pushes events to the Publisher.
///
/// - returns: AnyPublisher of the underlying Observable's Element type.
/// - note: This is a work around for a crash when using replaceError(with:)
public func asPublisherReplaceError(with: Element) -> AnyPublisher<Self.Element, Never> {
return self // NOTE: This crashes
.publisher
.replaceError(with: with)
.eraseToAnyPublisher()
// return self // NOTE: This works
// .publisher
// .catch({ _ -> AnyPublisher<Self.Element, Never> in
// Just(with).eraseToAnyPublisher()
// })
// .eraseToAnyPublisher()
}
}
class Bound<Value>: ObservableObject {
let bag = DisposeBag()
var value: Value {
didSet {
didChange.send(value)
}
}
let didChange = PassthroughSubject<Value, Never>()
init(_ value: Value) { self.value = value }
}
extension Observable {
func asBindableObject(initialValue: Element) -> Bound<Element> {
let bound = Bound(initialValue)
subscribe(onNext: { [weak bound] in bound?.value = $0 }).disposed(by: bound.bag)
return bound
}
}
class PublishedBehaviorRelay<T> {
typealias PublishType = AnyPublisher<T, Never>
typealias BindableType = Bound<T>
let dataSource: BehaviorRelay<T>
var bindable: BindableType {
return dataSource
.asObservable()
.asBindableObject(initialValue: dataSource.value)
}
var publisher: PublishType {
return dataSource
.asPublisherReplaceError(with: dataSource.value)
}
init(initialValue: T) {
dataSource = BehaviorRelay(value: initialValue)
}
}
class UserViewModel: ObservableObject {
@Published var sliderValue = 0.0
@Published var rxswift = "Boo Hiss"
var sliderString: String {
return "\(sliderValue)"
}
}
struct ContentView: View {
@ObservedObject private var userViewModel: UserViewModel
let relay = PublishedBehaviorRelay(initialValue: "Start")
var cancelables: Set<AnyCancellable> = []
let disposeBag = DisposeBag()
init() {
let uvm = UserViewModel()
userViewModel = uvm
// A publisher publishing numbers
let data = 0...1000
data
.publisher
.map({ "\($0)" })
.modulated(0.01, bufferSize: data.count, scheduler: RunLoop.main)
.eraseToAnyPublisher()
.asObservable()
.bind(to: relay.dataSource)
.disposed(by: disposeBag
)
// CRASH ON THIS LINE OF CODE
relay.publisher.assign(to: \.rxswift, on: uvm).store(in: &cancelables)
}
var body: some View {
VStack {
Slider(value: $userViewModel.sliderValue)
.padding(.horizontal, 40.0)
VStack {
Text("Hello, SwiftUI!")
.font(.largeTitle)
.foregroundColor(.green)
.padding(0.0)
Text(userViewModel.sliderString)
.font(.title)
.foregroundColor(Color.black)
.multilineTextAlignment(.center)
Text(userViewModel.rxswift)
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
This code works fine with the commented out asPublisherReplaceError(with:) but crashes in a different spot than it did before version 1.5 with the current implementation of asPublisherReplaceError(with:).
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
frame #0: 0x00007fff233b167a Combine`Combine.Publishers.ReplaceError.(Inner in _50EC2DA41500D4F648F58C2EE8939789).receive(A.Output) -> Combine.Subscribers.Demand + 314
frame #1: 0x00007fff233b1b70 Combine`protocol witness for Combine.Subscriber.receive(A.Input) -> Combine.Subscribers.Demand in conformance Combine.Publishers.ReplaceError<A>.(Inner in _50EC2DA41500D4F648F58C2EE8939789)<A1> : Combine.Subscriber in Combine + 16
frame #2: 0x0000000103ba2ae6 RxCombine`Subscriber<>.pushRxEvent(event=RxSwift.Event<τ_0_0.Input> @ scalar, self=<no summary available>) at Subscriber+Rx.swift:35:17
frame #3: 0x0000000103ba05e4 RxCombine`partial apply for Subscriber<>.pushRxEvent(_:) at <compiler-generated>:0
frame #4: 0x0000000103ca83fc RxSwift`closure #1 in ObservableType.subscribe(e=, on=0x0000000103ba05b0 RxCombine`partial apply forwarder for (extension in RxCombine):Combine.Subscriber< where A.Failure == Swift.Error>.pushRxEvent(RxSwift.Event<A.Input>) -> () at <compiler-generated>) at ObservableType+Extensions.swift:23:17
frame #5: 0x0000000103bd920f RxSwift`AnonymousObserver.onCore(event=, self=0x0000600001b8b570) at AnonymousObserver.swift:22:21
frame #6: 0x0000000103cb0ea1 RxSwift`ObserverBase.on(event=, self=0x0000600001b8b570) at ObserverBase.swift:16:22
frame #7: 0x0000000103cb1155 RxSwift`protocol witness for ObserverType.on(_:) in conformance ObserverBase<A> at <compiler-generated>:0
frame #8: 0x0000000103bec049 RxSwift`BehaviorSubject._synchronized_subscribe<Element>(observer=0x0000600001b8b570, self=0x00006000027a8120) at BehaviorSubject.swift:128:18
frame #9: 0x0000000103beba1c RxSwift`BehaviorSubject.subscribe<Element>(observer=0x0000600001b8b570, self=0x00006000027a8120) at BehaviorSubject.swift:111:33
frame #10: 0x0000000103ca833d RxSwift`ObservableType.subscribe(on=0x0000000103ba05b0 RxCombine`partial apply forwarder for (extension in RxCombine):Combine.Subscriber< where A.Failure == Swift.Error>.pushRxEvent(RxSwift.Event<A.Input>) -> () at <compiler-generated>, self=0x00006000027a8120) at ObservableType+Extensions.swift:25:40
frame #11: 0x0000000103ba0171 RxCombine`RxPublisher.receive<Upstream>(subscriber=<no summary available>, self=0x0000600001590e20) at Observable+Combine.swift:43:58
frame #12: 0x0000000103ba0455 RxCombine`protocol witness for Publisher.receive<A>(subscriber:) in conformance RxPublisher<A> at <compiler-generated>:0
frame #13: 0x00007fff233c1571 Combine`Combine.PublisherBox.receive<A where A1: Combine.Subscriber, A.Failure == A1.Failure, A.Output == A1.Input>(subscriber: A1) -> () + 33
frame #14: 0x00007fff233c1715 Combine`Combine.AnyPublisher.receive<A where A == A1.Input, B == A1.Failure, A1: Combine.Subscriber>(subscriber: A1) -> () + 53
frame #15: 0x00007fff2335eb59 Combine`(extension in Combine):Combine.Publisher.subscribe<A where A1: Combine.Subscriber, A.Failure == A1.Failure, A.Output == A1.Input>(A1) -> () + 873
frame #16: 0x00007fff233b1023 Combine`Combine.Publishers.ReplaceError.receive<A where A1: Combine.Subscriber, A.Output == A1.Input, A1.Failure == Swift.Never>(subscriber: A1) -> () + 371
frame #17: 0x00007fff233c1571 Combine`Combine.PublisherBox.receive<A where A1: Combine.Subscriber, A.Failure == A1.Failure, A.Output == A1.Input>(subscriber: A1) -> () + 33
frame #18: 0x00007fff233c1715 Combine`Combine.AnyPublisher.receive<A where A == A1.Input, B == A1.Failure, A1: Combine.Subscriber>(subscriber: A1) -> () + 53
frame #19: 0x00007fff2335eb59 Combine`(extension in Combine):Combine.Publisher.subscribe<A where A1: Combine.Subscriber, A.Failure == A1.Failure, A.Output == A1.Input>(A1) -> () + 873
frame #20: 0x00007fff2339d539 Combine`(extension in Combine):Combine.Publisher< where A.Failure == Swift.Never>.assign<A>(to: Swift.ReferenceWritableKeyPath<A1, A.Output>, on: A1) -> Combine.AnyCancellable + 265
* frame #21: 0x00000001035e8a22 SwiftUITest`ContentView.init() at ContentView.swift:62:25
frame #22: 0x00000001035d9847 SwiftUITest`SceneDelegate.scene(scene=0x00007fa1f0705940, session=0x0000600000083e00, connectionOptions=0x00006000015ad6c0, self=0x00006000015ad700) at SceneDelegate.swift:23:27
frame #23: 0x00000001035d9d36 SwiftUITest`@objc SceneDelegate.scene(_:willConnectTo:options:) at <compiler-generated>:0
frame #24: 0x00007fff4761d3e0 UIKitCore`+[UIScene _sceneForFBSScene:create:withSession:connectionOptions:] + 1304
frame #25: 0x00007fff4808f170 UIKitCore`-[UIApplication _connectUISceneFromFBSScene:transitionContext:] + 1018
frame #26: 0x00007fff4808f4b2 UIKitCore`-[UIApplication workspace:didCreateScene:withTransitionContext:completion:] + 304
frame #27: 0x00007fff47bfa7f5 UIKitCore`-[UIApplicationSceneClientAgent scene:didInitializeWithEvent:completion:] + 361
frame #28: 0x00007fff365d6165 FrontBoardServices`-[FBSSceneImpl _callOutQueue_agent_didCreateWithTransitionContext:completion:] + 442
frame #29: 0x00007fff365fc4d8 FrontBoardServices`__86-[FBSWorkspaceScenesClient sceneID:createWithParameters:transitionContext:completion:]_block_invoke.154 + 102
frame #30: 0x00007fff365e0c45 FrontBoardServices`-[FBSWorkspace _calloutQueue_executeCalloutFromSource:withBlock:] + 220
frame #31: 0x00007fff365fc169 FrontBoardServices`__86-[FBSWorkspaceScenesClient sceneID:createWithParameters:transitionContext:completion:]_block_invoke + 355
frame #32: 0x000000010400ad48 libdispatch.dylib`_dispatch_client_callout + 8
frame #33: 0x000000010400dcb9 libdispatch.dylib`_dispatch_block_invoke_direct + 300
frame #34: 0x00007fff3662237e FrontBoardServices`__FBSSERIALQUEUE_IS_CALLING_OUT_TO_A_BLOCK__ + 30
frame #35: 0x00007fff3662206c FrontBoardServices`-[FBSSerialQueue _queue_performNextIfPossible] + 441
frame #36: 0x00007fff3662257b FrontBoardServices`-[FBSSerialQueue _performNextFromRunLoopSource] + 22
frame #37: 0x00007fff23bd4471 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
frame #38: 0x00007fff23bd439c CoreFoundation`__CFRunLoopDoSource0 + 76
frame #39: 0x00007fff23bd3bcc CoreFoundation`__CFRunLoopDoSources0 + 268
frame #40: 0x00007fff23bce87f CoreFoundation`__CFRunLoopRun + 1263
frame #41: 0x00007fff23bce066 CoreFoundation`CFRunLoopRunSpecific + 438
frame #42: 0x00007fff384c0bb0 GraphicsServices`GSEventRunModal + 65
frame #43: 0x00007fff48092d4d UIKitCore`UIApplicationMain + 1621
frame #44: 0x00000001035d8e2b SwiftUITest`main at AppDelegate.swift:15:7
frame #45: 0x00007fff5227ec25 libdyld.dylib`start + 1
frame #46: 0x00007fff5227ec25 libdyld.dylib`start + 1
(lldb)
Stack frame 4 is this code
public func subscribe(_ on: @escaping (Event<Element>) -> Void)
-> Disposable {
let observer = AnonymousObserver { e in
on(e) <----- CRASH HERE
}
return self.asObservable().subscribe(observer)
}
A second issue showed up with replaceError(with:) in a more complicated piece of code.
This code works fine with the commented out asPublisherReplaceError(with:) but crashes in a different spot than it did before version 1.5 with the current implementation of asPublisherReplaceError(with:).
Stack frame 4 is this code