驱动器只能从 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 调用的主要内容,如果未能解决你的问题,请参考以下文章

Linux设备驱动之字符设备驱动

如何从驱动程序向另一个驱动程序(不在同一个堆栈中)进行 IOCTL 调用(在 Windows 上)

如何从不同的线程访问 MainThread 元素? [复制]

从 iCloud 驱动器获取文件而不下载?

如何从谷歌驱动器获取修订内容

如何使用 ODBC 驱动程序从 C# 调用 Progress Openedge .p 文件?