ReactiveCocoa6.0的开发指北

时间:2022-03-20 08:09:22

最新的ReactiveCocoa使用网上能找到的资料特别少,为了给接入swift版reactivecocoa的开发者提供便利,我就讲常用场景下的使用, 就拿注册页面来举例,如有异议和问题欢迎指正交流,言归正传,注册页面一般由一些信息需要用户填写,一般我们用UITableView展示,UITableView的使用我就不提了,上代码

fileprivate let verifyCode = MutableProperty<String>("")
....
func verifyCodeCell(at indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "verify_cell", for: indexPath) as! ABVerifyCodeCell

        self.verifyButton = cell.verifyCodeButton

        // import Then 
        return cell.with {
            $0.textField.reactive.text <~ self.verifyCode.producer.take(until: cell.reactive.prepareForReuse)
            $0.textField.reactive
                .continuousTextValues
                .take(until: cell.reactive.prepareForReuse)
                .map { $0 ?? "" }
                .observeValues{ [weak self] in
                    self?.verifyCode.value = String($0.characters.prefix(6))
            }

            $0.verifyCodeButton.reactive
                .controlEvents(.touchUpInside)
                .take(until: cell.reactive.prepareForReuse)
                .observeValues { [weak self] _ in
                    self?.getVerifyCode()
                }
        }
    }

由于cell重用问题,textField内容绑定必须调用以下方法来实现重用时解除之前的绑定

$0.textField.reactive.text <~ self.verifyCode.producer.take(until: cell.reactive.prepareForReuse)

以下代码用来限制输入的字符数,开发者也可以再次限制输入的内容,如手机号码校验等


.observeValues{ [weak self] in
                    self?.verifyCode.value = String($0.characters.prefix(6))
            }

一切尽在代码中,文笔太差就不多废话了

在需要多个请求都返回时才处理后续流程这种情况下,如果不使用ReactiveCocoa,需要保留很多状态
使用ReactiveCocoa就简单多了,贴代码

func requestPropertyValue() -> SignalProducer<PropertyValueModel, RequestError> {
        return SignalProducer { (observer, lifeTime) in
            let params = ["module" : PropertyValueService.ModuleProperty.prod.rawValue]

            let requestTask = PropertyValueService()
                .request(
                    params,
                    transform: {
                        var result = [String : String]()

                        $0["data"].arrayValue.forEach {
                            result[$0["mappingName"].stringValue] = $0["propName"].stringValue
                        }

                        return PropertyValueModel(propMap: result)
                    },
                    completionHandler: {
                        if $0.isSuccess {
                            observer.send(value: $0.value!)
                            observer.sendCompleted()
                        } else {
                            observer.send(error: $0.error as! RequestError)
                        }

                })

            lifeTime += AnyDisposable {
                requestTask?.cancel()
            }
        }
    }

    func requestProductCustomerNo() -> SignalProducer<String, NoError> {
        return SignalProducer { observer, _ in
            ProductNoService()
                .request(
                    nil,
                    transform: { $0["prodCustomNo"].stringValue },
                    completionHandler: {
                        observer.send(value: $0.isSuccess ? $0.value! : "")
                        observer.sendCompleted()
                })
        }
    }

    func requestCustomerNoAndPropertyValue() {
        let customerNoProducer = requestProductCustomerNo().promoteError(RequestError.self)
        let propProducer = requestPropertyValue()

        customerNoProducer
            .combineLatest(with: propProducer)
            .observe(on: UIScheduler())
            .on(starting: { [weak self] _ in
                if let strongSelf = self {
                    strongSelf.showLoadingOnView(strongSelf.view)
                }
            })
            .startWithSignal { signal, _ in
                signal.observeResult { [weak self] result in
                    if let strongSelf = self {
                        strongSelf.hideLoadingForView(strongSelf.view)

                        if let value = result.value {
                            strongSelf.customNo.value = value.0
                            strongSelf.generatedProdNo = value.0
                            strongSelf.tableView.reloadData()
                        }
                    }
                }
            }
    }

combineLatest函数使多个信号都响应时才通知,不需要保留任何临时状态就优雅的解决了这种问题