欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

RxSwift官方实例(API包装UI控件处理和详细使用)

程序员文章站 2022-03-18 23:48:11
代码下载UI搭建下图UI:UI控件处理简单控件处理首先定义一个用于显示信息的函数: func debug(_ param: String) { print(param) label.text = param }UITapGestureRecognizer处理: pan.rx.event.subscribe(onNext: { if self.textField.isFirstResponder || se...

代码下载

UI

搭建下图UI:
RxSwift官方实例(API包装UI控件处理和详细使用)

UI控件处理

简单控件处理

首先定义一个用于显示信息的函数:

 func debug(_ param: String) {
        print(param)
        label.text = param
    } 

UITapGestureRecognizer处理:

 pan.rx.event.subscribe(onNext: {
            if self.textField.isFirstResponder || self.textField1.isFirstResponder || self.textView.isFirstResponder || self.textView1.isFirstResponder {
                self.view.endEditing(true)
            } else {
                self.debug("UIGestureRecognizer event \($0.state.rawValue)")
            }
        }).disposed(by: bag) 

UIBarButtonItem处理:

 item.rx.tap.bind {
            self.debug("UIBarButtonItem Tapped")
        }.disposed(by: bag) 

UISlider处理:

 slider.rx.value.subscribe(onNext: {
            self.debug("UISlider value \($0)")
        }).disposed(by: bag) 

UIButton处理:

 button.rx.tap.subscribe(onNext: {
            self.debug("UIButton Tapped")
        }).disposed(by: bag) 

UIDatePicker处理:

 datePicker.rx.date.subscribe(onNext: {
            self.debug("UIDatePicker date \($0)")
        }).disposed(by: bag) 

CLLocationManager处理:

 let manager = CLLocationManager()
        manager.startUpdatingLocation()
        manager.rx.didChangeAuthorization.subscribe(onNext: { (pair) in
            let value = "定位权限状态:\(pair.1)"
            self.debug(value)
        }).disposed(by: bag) 

双向绑定

双向绑定是通过BehaviorRelay来实现的,定义如下<->操作符方便UI控件的ControlProperty序列的双向绑定:

func <-><T>(property: ControlProperty<T>, relay: BehaviorRelay<T>) -> Disposable {
#if DEBUG
    if T.self == String.self {
        fatalError("删除这个信息也是可以的,但是这是在提醒开发者有可能试着将一些“rx.text”属性绑定到relay。\n" +
            "这通常能够很好的工作,但是对于一些IME语言这种简单的方法将造成意外的问题,因为当文本正在输入时将会返回中间结果。\n" +
            "解决方案: 就是使用 `textField <-> relay` 替换 `textField.rx.text <-> relay`.\n" +
        "了解更多: https://github.com/ReactiveX/RxSwift/issues/649\n")
    }
#endif
    
    let bind = relay.bind(to: property)
    let bindRelay = property.subscribe(onNext: { (n) in
        relay.accept(n)
    }, onCompleted: {
        bind.dispose()
    })
    
    return Disposables.create(bind, bindRelay)
} 

代码分析:

  1. 将BehaviorRelay序列的值绑定到ControlProperty序列上
  2. 订阅ControlProperty序列的值
  3. ControlProperty序列发出元素时BehaviorRelay序列也通过accept操作符发出元素,完成时通过dispose操作符清理BehaviorRelay序列
  4. 返回订阅ControlProperty序列的Disposable

注意:
在这里有一个问题就是当对字符串文本进行双向绑定时,因为当文本正在输入时将会返回中间结果,对于一些IME语言这种简单的方法将造成意外的问题。解决方案就是使用 textField <-> relay 替换 textField.rx.text <-> relay

具体代码代码实现:

func <-><Base>(textInput: TextInput<Base>, relay: BehaviorRelay<String>) -> Disposable {
    let bind = relay.bind(to: textInput.text)
    let bindRelay = textInput.text.subscribe(onNext: { (n) in
        if let nonMarkedText = nonMarkedText(textInput.base), nonMarkedText != relay.value {
            relay.accept(nonMarkedText)
        }
    }, onCompleted: {
        bind.dispose()
    })
    
    return Disposables.create(bind, bindRelay)
} 

UISegmentedControl处理:

 let value = BehaviorRelay(value: 0)
        _ = segmentedControl.rx.value <-> value
        value.asObservable().subscribe(onNext: { (v) in
            self.debug("UISegmentedControl value \(v)")
        }).disposed(by: bag) 

UISwitch处理:

 let switchV = BehaviorRelay(value: true)
        _ = switcher.rx.value <-> switchV
        switchV.asObservable().subscribe(onNext: {
            self.debug("UISwitch value \($0)")
        }).disposed(by: bag)
        switcher.rx.value.bind(to: activityIndicator.rx.isAnimating).disposed(by: bag) 

UITextField处理:

 // MARK: UITextField

        // 在ios 11.2中存在内存泄漏
        //
        // 最终的类UITextFieldSubclass: UITextField { deinit { print("不会调用")  } }
        if #available(iOS 11.2, *) {
            let textV = BehaviorRelay(value: "")
            _ = textField.rx.textInput <-> textV
            textV.asObservable().subscribe(onNext: {
                self.debug("UITextField text \($0)")
            }).disposed(by: bag)
            
            let textV1 = BehaviorRelay<NSAttributedString?>(value: NSAttributedString(string: ""))
            _ = textField1.rx.attributedText <-> textV1
            textV1.asObservable().subscribe(onNext: {
                self.debug("UITextField attributedText \($0?.description ?? "")")
            }).disposed(by: bag)
        } 

注意:在ios 11.2中存在内存泄漏,继承自UITextField最终的类不会执行deinit函数。

UITextView处理:

 let textViewV = BehaviorRelay(value: "")
        _ = textView.rx.textInput <-> textViewV
        textViewV.asObservable().subscribe(onNext: {
            self.debug("UITextView text \($0)")
        }).disposed(by: bag)
        
        let textViewV1 = BehaviorRelay<NSAttributedString?>(value: NSAttributedString(string: ""))
        _ = textView1.rx.attributedText <-> textViewV1
        textViewV1.asObservable().subscribe(onNext: {
            self.debug("UITextView attributedText \($0?.description ?? "")")
        }).disposed(by: bag) 

本文地址:https://blog.csdn.net/jiuchabaikaishui/article/details/107865609