Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
RxSwift:如何正确订阅变量更改_Swift_Rx Swift - Fatal编程技术网

RxSwift:如何正确订阅变量更改

RxSwift:如何正确订阅变量更改,swift,rx-swift,Swift,Rx Swift,我有两个屏幕: NewControlTableViewController:包含一个文本字段,用于从其他视图中选择客户端 ClientsTableViewController:第二个视图包含可选择的客户端列表 这两个屏幕共享一个viewmodel 这是我的代码: import RxSwift import RxCocoa struct NewControlViewModel { var selectedClient = Variable<Client>(Client()

我有两个屏幕:

  • NewControlTableViewController
    :包含一个文本字段,用于从其他视图中选择客户端
  • ClientsTableViewController
    :第二个视图包含可选择的客户端列表
  • 这两个屏幕共享一个viewmodel

    这是我的代码:

    import RxSwift
    import RxCocoa
    struct NewControlViewModel {
         var selectedClient = Variable<Client>(Client())
         // other stuff
    }
    // NewControlTableViewController : viewDidLoad
    viewModel.selectedClient.asObservable().subscribe { event in
            debugPrint(event)
    }
    // ClientsTableViewController: viewDidLoad
    
    /*tableView.rx.itemSelected.subscribe(onNext: { indexPath in
            let client = self.clients[indexPath.row]
            debugPrint(client)
            self.viewModel.selectedClient.value = client
            self.navigationController?.popToRootViewController(animated: true)
    
        }).disposed(by: self.disposeBag)*/
       // new code
       tableView.rx
            .modelSelected(Client.self)
            .debug("client selected", trimOutput: true)
            .do(onNext: { _ in
                self.navigationController?.popViewController(animated: true)
            })
            .subscribe(onNext: { client in
                debugPrint(client)
                self.viewModel.selectedClient.value = client
            }, onError: { error in
            debugPrint(error)
        }).disposed(by: disposeBag)
    
    导入RxSwift
    进口RxCocoa
    结构NewControlViewModel{
    var selectedClient=变量(Client())
    //其他东西
    }
    //NewControlTableViewController:viewDidLoad
    viewModel.selectedClient.asObservable().subscribe{event in
    调试打印(事件)
    }
    //ClientsTableViewController:viewDidLoad
    /*tableView.rx.itemSelected.subscribe(onNext:{indepath in
    让client=self.clients[indexPath.row]
    调试打印(客户端)
    self.viewModel.selectedClient.value=client
    self.navigationController?.popToRootViewController(动画:true)
    }).处置(由:self.disposeBag)*/
    //新代码
    tableView.rx
    .modelSelected(Client.self)
    .debug(“已选择客户端”,输出:true)
    .do(onNext:{uu}in
    self.navigationController?.popViewController(动画:true)
    })
    .subscribe(onNext:{client in
    调试打印(客户端)
    self.viewModel.selectedClient.value=client
    },onError:{中有错误
    调试打印(错误)
    }).处置(由:处置人)
    

    每当我查看第一个屏幕时,就会触发事件(带有空值),然后,在从第二个屏幕选择客户端后,出于某种原因,不会触发任何事件。

    首先,不推荐使用
    变量

    您应该使用不需要初始值的
    PublishRelay
    ,这样它就不会在您的第一个屏幕中订阅时触发。 继电器的优点是它们不会出错或不完整

    struct NewControlViewModel {
      let selectedClient = PublishRelay<Client>()
    }
    
    // NewControlTableViewController : viewDidLoad
    choisirMandat.rx.tap.subscribe(onNext: { [unowned self] in
      let viewController = /* instantiate vc */
    
      // Make sure to use the same viewModel
      viewController.viewModel = self.viewModel
    
      self.present(viewController, animated: true)
    }).disposed(by: disposeBag)
    
    self.viewModel.selectedClient.debug().subscribe().disposed(by: self.disposeBag)
    
    // ClientsTableViewController: viewDidLoad
    tableView.rx.itemSelected.map { [unowned self] indexPath in
      return self.clients[indexPath.row]
    }
    .debug("client selected", trimOutput: true)
    .do(onNext: { [unowned self] _ in
      self.navigationController?.popToRootViewController(animated: true)
    })
    .bind(to: self.viewModel.selectedClient)
    .disposed(by: self.disposeBag)
    
    struct NewControlViewModel{
    让selectedClient=PublishRelay()
    }
    //NewControlTableViewController:viewDidLoad
    choisirMandat.rx.tap.subscribe(onNext:{[unowned self]在
    让viewController=/*实例化vc*/
    //确保使用相同的viewModel
    viewController.viewModel=self.viewModel
    self.present(viewController,动画:true)
    }).处置(由:处置人)
    self.viewModel.selectedClient.debug().subscribe().disposed(由:self.disposeBag)
    //ClientsTableViewController:viewDidLoad
    tableView.rx.itemSelected.map{[unowned self]indexath在
    返回self.clients[indexPath.row]
    }
    .debug(“已选择客户端”,输出:true)
    .do(onNext:{[unowned self]uuu in
    self.navigationController?.popToRootViewController(动画:true)
    })
    .bind(到:self.viewModel.selectedClient)
    .处置(由:self.disposeBag)
    
    另一方面,如果您想充分发挥功能,客户机可能也应该来自Rx世界。 另一方面,您可以使用
    debug()
    操作符打印事件


    bind(to:)
    是在RxSwift 4.1中添加的,因此请确保是最新的

    我想我在这里发现了您的问题。你在做什么

    // NewControlTableViewController : viewDidLoad
    viewModel.selectedClient.asObservable().subscribe { event in
        debugPrint(event)
    }
     // ClientsTableViewController: viewDidLoad
    
    tableView.rx.itemSelected.subscribe(onNext: { indexPath in
        let client = self.clients[indexPath.row]
        debugPrint(client)
        self.viewModel.selectedClient.value = client
        self.navigationController?.popToRootViewController(animated: true)
    
    }).disposed(by: self.disposeBag)
    
    您需要更改此行“self.viewModel.selectedClient.value=client”。您需要使用以前的控制器实例或NewControlTableViewController实例,如self.newControlTableVC.selectedClient.value=client

    我认为您正试图通过将NewControlTableViewController中的值发送到ClientsTableViewController来使用viewmodel

    此外,我做了与您相同的场景,在我的案例中效果非常好。只要试试我的方案,如果它不能工作,一定有一些小问题


    我希望这可能会有所帮助

    您是否忘记在
    NewControlTableViewController
    中使用
    .disposed(by:)
    ?该
    dispose
    方法用于在控制器解除分配后处理流。在这种情况下不重要!:)你确定你没有在过程中的某个地方变异
    selectedClient
    ?做一个
    检查一下。你能解释一下吗。我没有收到你的信question@TimofeySolonin我需要将
    selectedClient
    设置为可变的,以便在用户选择客户端时,我可以稍后对其进行更改。这是错误的。试着制作一个类似于OP文章中描述的场景,它会按照预期工作。当struct被传递时,它将复制所有包含的引用类型。@timofeysolon嘿,你说得对。我做了同样的场景,它对我有效。我的问题是使用同一
    viewModel
    对象的两个不同实例。而不是这样做,我将把viewModel对象传递给
    ClientsViewController
    的viewModel对象,因此现在两者共享同一个实例!