Swift笔记 - 18.响应式编程、Swift源码分析

响应式编程

  • 响应式编程(ReactiveProgramming,简称RP)

    • 也是一种编程范式,于1997年提出,可以简化异步编程,提供更优雅的数据绑定
    • 一般与西数式融合在一起,所以也会叫做:函数响应式编程(Functional Reactive Programming,简称FRP
  • 比较著名的、成熟的响应式框架

  • RxSwift

    • RxSwift ( ReactiveX for Swift ) , ReactiveX 的 Swift 版本
      • 源码:https://github.com/ReactiveX/RxSwift
      • 中文文档:https://beeth0ven.github.io/RxSwift-Chinese-Documentation/
  • RxSwif的github上已经有详细的安装教程,这里只演示CocoaPods方式的安装

  • 模块说明

    • RxSwift:Rx标准API的Swift实现,不包括任何iOS相关的内容
    • RxCocoa:基于RxSwift,给iOS UI控件扩展了很多Rx特性
  • RxSwift核心角色

    • Observable:负责发送事件(Event)
    • Observer:负责订阅Observable,监听Observable发送的事件(Event)
    • Event有3种
      • next:携带具体数据
      • error:携带错误信息,表明Observable终止,不会再发出事件
      • completed:表明Observable终止,不会再发出事件
public enum Event<Element> {
    /// Next element is produced.
    case next(Element)
    /// Sequence terminated with an error.
    case error(Swift.Error)
    /// Sequence completed successfully.
    case completed
}
  • 创建订阅Observable
var observable = Observable«Int>.create { observer in
observer.onNext(1)
observer.onCompleted()
return Disposables.create()
}
//等价于
observable = Observable.just (1)
observable = Observable.of(1)
observable = Observable.from([1])
var observable = Observable<Int>.create { observer in
    observer.onNext(1)
    observer.onNext(2)
    observer.onNext(3)
    observer.onCompleted()
    return Disposables.create()
}
// 等价于
observable = Observable.of(1, 2, 3)
observable = Observable.from([1, 2, 31)
observable.subscribe { event
    print(event)
}.dispose()

observable. subscribe (onNext:
    print("next", $0)
}, .onError: {
    print("error", $0)
}, .onCompleted: {
    print("completed")
}, onDisposed: {
    print("dispose")
}).dispose()
  • 让UI组件去订阅监听
    • 让label绑定订阅一个定时器的observable
let observable = Observable<Int>.timer(.seconds(2), period: .seconds(1), scheduler: MainScheduler. instance)
observable.map{ "数值是:\($0)" }.bind(to:label.rx.text)
  • 绑到按钮上让它闪动
let observable = Observable<Int.timer(.seconds(2), period: .seconds(1), scheduler:MainScheduler.instance)
let binder = Binder<Bool>(button){ button, value in
    button.isHidden = value
}
observable.map { $0 % 2 == 0 }.bind(to: binder).disposed(by: bag)
  • Disposable 取消订阅
    • 每当Observable被订阅时,都会返回一个Disposable实例,当调用Disposable的dispose,就相当于取消订阅
    • 在不需要再接收事件时,建议取消订阅,释放资源。有3种常见方式取消订阅
//立即取消订间(一次性订阅)
observable.subscribe { event in
    print(event)
}.dispose()

//当bag销毁 (deinit) 时,会自动调用Disposable实例的dispose
observable.subscribe { event in
    print (event)
}.disposed(by: bag)

// self销毁 (deinit) 时,会自动调用Disposable实例的dispose
let _ = observable.takeUntil(self.rx.deallocated).subscribe { event in
    print(event)
}
  • 创建Observer
let observer = AnyObserver<Int>.init{ event in
    switch event {
        case .next(let data):
            print (data)
        case .completed:
            print ("completed")
        case .error(let error):
            print("error", error)
    }
}
Observable. just (1).subscribe(observer).dispose()

let binder = Binder<String>(label) { label, text in
label.text = text
Observable.just(1).map { "数值是\($0)" }.subscribe(binder).dispose()
Observable.just(1).map { "数值是\($0)" }.bind(to: binder).dispose)
  • 扩展 UIControl 的 rx 属性
extension Reactive where Base: UIControl
    var hidden: Binder<Bool> {
        Binder<Bool>(base) { button, value in
            button.isHidden = value
        }
    }
    var enabled: Binder<Bool> {
        Binder<Bool> (base) { button, value in
            bytton.isEnabled = value
        }
    }
}
  • 使用案例
struct Person {
var name: String
var age: Int
}
class ViewController: UIViewController {
    @IBOutlet weak var slider: UISlider!
    @IBOutlet weak var tableView: UITableView!
    @IBOutlet weak var button: UIButton!
    @IBOutlet weak var label: UILabel!
    @IBOutlet weak var textField: UITektField!
    let bag = DisposeBag()
    let persons = Observable.just([
        Person(name: "Jack", age: 20),
        Person(name: "Rose", age: 22),
        Person(name: "Kate", age: 25)
    ])
    override func viewDidLoad() {
        super.viewDidLoad()
        persons.bind(to: tableView.rx.items(cellIdentifier: "cell")) 
              { row, person, cell in
            cell. textLabel?.text = person.name
            cell.detailTextlabel?.text = "\(person.age)"
        }.disposed(by: bag)
        
        tableView.rx.itemSelected.subscribe(onNext: { path in
            print("At7", path)
        }).disposed(by: bag)
        
        //tableView.rx.modelSelected(Person.self).subscribe (onNext: { person in
        //    print("At7", person)
        //}).disposed(by: bag)
    }
    
    func test2() {
        Observable.just (0.8).bind(to:
        slider.rx.value).disposed(by: bag)
        slider.rx.value.map ( "slider数值是\(S0)" ).bind(to: textfield.rx.text).disposed(by: bag)
    	
        textField.rx.text.subscribe(onNext: { text in
    	       print(text ?? "")
        }).disposed(by: bag)
    	
        button.rx.controlEvent(.touchUpInside).subscribe(onNext:
    	        print("按钮被点击了"
        )).disposed(py: bag)
    	
        let observable = Observable<Int>.timer(.seconds (2), period: .seconds(1), scheduler: MainScheduler.instance)
        let binder = Binder<Bool>(button)( button, value in
    	        button.isHidden = value
        }
        observable.map ( "\($0)" ).bind(to: 1abel.rx.text).disposed(by:bag)
    }
}

Swift源码分析

继续阅读