驱动器只能从 MainThread 调用
Posted
技术标签:
【中文标题】驱动器只能从 MainThread 调用【英文标题】:drive can be only called from MainThread 【发布时间】:2019-02-10 12:51:48 【问题描述】:在通过代码呈现新的 UIViewController 之后,在使用 .Drive 的每个位置(在 viewModel 或 viewController 中),我都会收到此错误:
drive* family of methods can be only called from MainThread
这就是我展示新 ViewController 的方式:
func goToVerifyPage()
let verifyVC = VerifyViewController()
verifyVC.modalTransitionStyle = .flipHorizontal
self.present(verifyVC, animated: true, completion: nil)
在VerifyViewController内部:
override func viewDidLoad()
super.viewDidLoad()
confirmVerifyCodeBTN.rx.tap
.asDriver()
.debounce(1)
.filter(
self.viewModel.signupEnabled
)
.drive(onNext: [weak self] _ in
guard let verifyCode = self?.verificationCodeTF.text else return
self?.verifyActivateCode(verifyCode)
).disposed(by: disposeBag)
执行 .filter 行后显示的错误。
在之前的 viewController(名为 loginViewController)中,我使用相同的代码,但没有收到任何错误,verifyViewController 和 loginViewController 之间唯一不同的是,使用情节提要来呈现该 ViewController(loginViewController)。
更新: 当我使用此代码呈现 verifyViewController 时,一切正常:
func goToVerifyPage()
DispatchQueue.main.async
let verifyVC = VerifyViewController()
verifyVC.modalTransitionStyle = .flipHorizontal
self.present(verifyVC, animated: true, completion: nil)
【问题讨论】:
你的问题到底是什么? 为什么会这样?以及如何让代码运行? 发生这种情况是因为您没有按照库的要求在主线程上运行代码。而且你必须将它分派到正确的线程。 在confirmVerifyCodeBTN.rx.tap 行之前,我把Thread.isMainThread 和它返回true。每次我想使用 dispatch 呈现新的 ViewController 时,我认为这不是正确的方法。 添加 DispatchQueue.main.async 是一个很好的解决方案。更符合 rx-swift 的方式是使用:.observeOn(MainScheduler.instance)
【参考方案1】:
我猜你是从 URLSession 的网络请求的结果中调用goToVerifyPage()
。 URLSession 在后台线程上发出它的值,所以当你准备好切换到主线程时,你应该有一个.observeOn(MainThread.instance)
。
【讨论】:
你是对的。但你能解释一下为什么 Thread.isMainThread 返回 true 吗? (我在 VerifyViewController 中的 confirmVerifyCodeBTN.rx.tap 行之前放置了 Thread.isMainThread 代码) 没有足够的代码来重现该问题,所以我无法告诉您原因。我的猜测是根据我自己以前的经验。这是我自己陷入的陷阱。以上是关于驱动器只能从 MainThread 调用的主要内容,如果未能解决你的问题,请参考以下文章
如何从驱动程序向另一个驱动程序(不在同一个堆栈中)进行 IOCTL 调用(在 Windows 上)