RXSwift,检测到可重入异常

10

我是RXSwift的初学者,我的代码出了问题。

下面是我的代码:

let dartScore = PublishSubject<Int>()
            dartScore.asObservable()
                .scan(501) { intermediate, newValue in
                    let result = intermediate - newValue
                    return result >= 0 ? result : intermediate
                }
                .do(onNext: {
                    if $0 == 0 {
                        dartScore.onCompleted()
                    }
                })
                .subscribe({
                    print($0.isStopEvent ? $0 : $0.element!)
                })
                .disposed(by: disposeBag)

            dartScore.onNext(13)
            dartScore.onNext(50)
            dartScore.onNext(60)
            dartScore.onNext(378)

我遇到了错误:

⚠️ 检测到重入异常。 ⚠️

调试:您可以在 /****RxSwift/RxSwift/Rx.swift:97 中设置断点并观察调用堆栈来调试此问题。

问题:这种行为破坏了可观察序列语法。next (error | completed)? 这种行为破坏了语法,因为序列事件之间存在重叠。可观察序列正试图在前一个事件发送完成之前发送事件。

为什么我不能在 .do(onNext) 内部执行 ".onCompleted()",我应该怎么做才能避免警告?

我使用的是 XCode 9.0、swift 4 和 RXSwift 4.0.0。

谢谢

最好的问候


2
我是一个 Rx.NET 的用户,但我认为 RxSwift 表现方式相同 - 因此不要在 do 中使用 .onCompleted()。你可能想使用 takeWhile - Enigmativity
感谢您的建议,@Enigmtivity, 敬礼 - Seishin Okigaru
4
因为完全无关的代码,我遇到了这个问题。如果你按照指示设置断点并观察堆栈,就可以跟踪问题。对于我来说,我在观察文本字段并计算和设置其他值。因此,用于计算其他值的代码调用了view.endEditing(true),因此它进入了编辑和结束编辑的循环中。 - Skywalker
2个回答

12

你不能在.onNext()中放置.onCompleted(),因为这会导致可观察对象吃掉自己的尾巴,从而引起内存循环。

正如评论区@Enigmativity提到的,你应该使用takeWhile()来处理这种情况:

dartScore.asObservable()
    .scan(501) { intermediate, newValue in
        let result = intermediate - newValue
        return result >= 0 ? result : intermediate
    }
    .takeWhile { $0 != 0 }
    .subscribe({
        print($0.isStopEvent ? $0 : $0.element!)
    })

上面的代码创建了一个新的可观察对象,当值为0时它将完成。


哦,好的,明白了,谢谢你的回答 :) 祝好 - Seishin Okigaru
我有两行连续的代码,像这样:observer.onNext("Hello world"); observer.onCompleted() 这样做有问题吗? - mfaani
@Honey 不,没问题(假设您没有将这两行代码放在绑定到observer的闭包中)。 - Daniel T.

0

虽然与问题本身不直接相关,但我在搜索“检测到重入异常”时来到这里,对我来说原因很简单,即在MacOs上为NSView的代码中删除了一行addSubview(viewInQuestion),同时仍在约束设置中使用viewInQuestion......将viewInQuestion添加为子视图解决了这个问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接