zoukankan      html  css  js  c++  java
  • [RxSwift教程]19、特征序列3:ControlProperty、 ControlEvent

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
    ➤微信公众号:山青咏芝(let_us_code)
    ➤博主域名:https://www.zengqiang.org
    ➤GitHub地址:https://github.com/strengthen/LeetCode
    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

    五、ControlProperty

    1,基本介绍

    (1)ControlProperty 是专门用来描述 UI 控件属性,拥有该类型的属性都是被观察者(Observable)。
    (2)ControlProperty 具有以下特征:
    • 不会产生 error 事件
    • 一定在 MainScheduler 订阅(主线程订阅)
    • 一定在 MainScheduler 监听(主线程监听)
    • 共享状态变化
     

    2,使用样例

    (1)其实在 RxCocoa 下许多 UI 控件属性都是被观察者(可观察序列)。比如我们查看源码(UITextField+Rx.swift),可以发现 UITextField 的 rx.text 属性类型便是 ControlProperty<String?>:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    import RxSwift
    import UIKit
     
    extension Reactive where BaseUITextField {
     
        public var text: ControlProperty<String?> {
            return value
        }
     
        public var value: ControlProperty<String?> {
            return base.rx.controlPropertyWithDefaultEvents(
                getter: { textField in
                    textField.text
            },
                setter: { textField, value in
                    if textField.text != value {
                        textField.text = value
                    }
            }
            )
        }
         
        //......
    }


    (2)那么我们如果想让一个 textField 里输入内容实时地显示在另一个 label 上,即前者作为被观察者,后者作为观察者。可以这么写:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    import UIKit
    import RxSwift
    import RxCocoa
     
    class ViewControllerUIViewController {
         
        @IBOutlet weak var textField: UITextField!
         
        @IBOutlet weak var label: UILabel!
         
        let disposeBag = DisposeBag()
         
        override func viewDidLoad() {
             
            //将textField输入的文字绑定到label上
            textField.rx.text
                .bind(to: label.rx.text)
                .disposed(by: disposeBag)
        }
    }
     
    extension UILabel {
        public var fontSize: Binder<CGFloat> {
            return Binder(self) { label, fontSize in
                label.font = UIFont.systemFont(ofSize: fontSize)
            }
        }
    }


    (3)运行结果如下:

    原文:Swift - RxSwift的使用详解19(特征序列3:ControlProperty、 ControlEvent)

    六 、ControlEvent

    1,基本介绍

    (1)ControlEvent 是专门用于描述 UI 所产生的事件,拥有该类型的属性都是被观察者(Observable)。
    (2)ControlEvent 和 ControlProperty 一样,都具有以下特征:
    • 不会产生 error 事件
    • 一定在 MainScheduler 订阅(主线程订阅)
    • 一定在 MainScheduler 监听(主线程监听)
    • 共享状态变化
     

    2,使用样例

    (1)同样地,在 RxCocoa 下许多 UI 控件的事件方法都是被观察者(可观察序列)。比如我们查看源码(UIButton+Rx.swift),可以发现 UIButton 的 rx.tap 方法类型便是 ControlEvent<Void>:
    1
    2
    3
    4
    5
    6
    7
    8
    import RxSwift
    import UIKit
     
    extension Reactive where BaseUIButton {
        public var tap: ControlEvent<Void> {
            return controlEvent(.touchUpInside)
        }
    }


    (2)那么我们如果想实现当一个 button 被点击时,在控制台输出一段文字。即前者作为被观察者,后者作为观察者。可以这么写:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    import UIKit
    import RxSwift
    import RxCocoa
     
    class ViewControllerUIViewController {
         
        let disposeBag = DisposeBag()
         
        @IBOutlet weak var button: UIButton!
         
        override func viewDidLoad() {
             
            //订阅按钮点击事件
            button.rx.tap
                .subscribe(onNext: {
                    print("欢迎访问hangge.com")
                }).disposed(by: disposeBag)
        }
    }


    (3)运行结果如下:

        原文:Swift - RxSwift的使用详解19(特征序列3:ControlProperty、 ControlEvent)      原文:Swift - RxSwift的使用详解19(特征序列3:ControlProperty、 ControlEvent)
     

    附:给 UIViewController 添加 RxSwift 扩展

    1,UIViewController+Rx.swift

    这里我们对 UIViewController 进行扩展:

    • 将 viewDidLoad、viewDidAppear、viewDidLayoutSubviews 等各种 ViewController 生命周期的方法转成 ControlEvent 方便在 RxSwift 项目中使用。
    • 增加 isVisible 序列属性,方便对视图的显示状态进行订阅。
    • 增加 isDismissing 序列属性,方便对视图的释放进行订阅。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    import UIKit
    import RxCocoa
    import RxSwift
     
    public extension Reactive where BaseUIViewController {
        public var viewDidLoad: ControlEvent<Void> {
            let source = self.methodInvoked(#selector(Base.viewDidLoad)).map { _ in }
            return ControlEvent(events: source)
        }
         
        public var viewWillAppear: ControlEvent<Bool> {
            let source = self.methodInvoked(#selector(Base.viewWillAppear))
                .map { $0.first asBool ?? false }
            return ControlEvent(events: source)
        }
        public var viewDidAppear: ControlEvent<Bool> {
            let source = self.methodInvoked(#selector(Base.viewDidAppear))
                .map { $0.first asBool ?? false }
            return ControlEvent(events: source)
        }
         
        public var viewWillDisappear: ControlEvent<Bool> {
            let source = self.methodInvoked(#selector(Base.viewWillDisappear))
                .map { $0.first asBool ?? false }
            return ControlEvent(events: source)
        }
        public var viewDidDisappear: ControlEvent<Bool> {
            let source = self.methodInvoked(#selector(Base.viewDidDisappear))
                .map { $0.first asBool ?? false }
            return ControlEvent(events: source)
        }
         
        public var viewWillLayoutSubviews: ControlEvent<Void> {
            let source = self.methodInvoked(#selector(Base.viewWillLayoutSubviews))
                .map { _ in }
            return ControlEvent(events: source)
        }
        public var viewDidLayoutSubviews: ControlEvent<Void> {
            let source = self.methodInvoked(#selector(Base.viewDidLayoutSubviews))
                .map { _ in }
            return ControlEvent(events: source)
        }
         
        public var willMoveToParentViewController: ControlEvent<UIViewController?> {
            let source = self.methodInvoked(#selector(Base.willMove))
                .map { $0.first asUIViewController }
            return ControlEvent(events: source)
        }
        public var didMoveToParentViewController: ControlEvent<UIViewController?> {
            let source = self.methodInvoked(#selector(Base.didMove))
                .map { $0.first asUIViewController }
            return ControlEvent(events: source)
        }
         
        public var didReceiveMemoryWarning: ControlEvent<Void> {
            let source = self.methodInvoked(#selector(Base.didReceiveMemoryWarning))
                .map { _ in }
            return ControlEvent(events: source)
        }
         
        //表示视图是否显示的可观察序列,当VC显示状态改变时会触发
        public var isVisible: Observable<Bool> {
            let viewDidAppearObservable = self.base.rx.viewDidAppear.map { _ in true }
            let viewWillDisappearObservable = self.base.rx.viewWillDisappear
                .map { _ in false }
            return Observable<Bool>.merge(viewDidAppearObservable,
                                          viewWillDisappearObservable)
        }
         
        //表示页面被释放的可观察序列,当VC被dismiss时会触发
        public var isDismissing: ControlEvent<Bool> {
            let source = self.sentMessage(#selector(Base.dismiss))
                .map { $0.first asBool ?? false }
            return ControlEvent(events: source)
        }
    }

    2,使用样例

    (1)通过扩展,我们可以直接对 VC 的各种方法进行订阅。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    import UIKit
    import RxSwift
    import RxCocoa
     
    class ViewControllerUIViewController {
     
        let disposeBag = DisposeBag()
         
        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
             
            //页面显示状态完毕
            self.rx.isVisible
                .subscribe(onNext: { visible in
                    print("当前页面显示状态:(visible)")
                }).disposed(by: disposeBag)
             
            //页面加载完毕
            self.rx.viewDidLoad
                .subscribe(onNext: {
                    print("viewDidLoad")
                }).disposed(by: disposeBag)
             
            //页面将要显示
            self.rx.viewWillAppear
                .subscribe(onNext: { animated in
                    print("viewWillAppear")
                }).disposed(by: disposeBag)
             
            //页面显示完毕
            self.rx.viewDidAppear
                .subscribe(onNext: { animated in
                    print("viewDidAppear")
                }).disposed(by: disposeBag)
        }
         
        override func viewDidLoad() {
            super.viewDidLoad()
        }
    }


    (2)运行结果如下:

    原文:Swift - RxSwift的使用详解19(特征序列3:ControlProperty、 ControlEvent)
  • 相关阅读:
    图像的纹理分析
    图像的小波变换
    图像的哈尔变换
    图像的K-L变换
    图像的斜变换
    图像的波尔什-哈达玛变换
    今日心得:给自己写信
    今日心得:人的幸福感取决于什么?
    今日心得:人生就像一杯茶,不会苦一辈子但会苦一阵子
    今日心得:纪念徐志摩117周年
  • 原文地址:https://www.cnblogs.com/strengthen/p/13675147.html
Copyright © 2011-2022 走看看