Swift笔记 - 18.响应式编程、Swift源码分析
Swift笔记 - 18.响应式编程、Swift源码分析
响应式编程
- 响应式编程(ReactiveProgramming,简称RP)
- 也是一种编程范式,于1997年提出,可以简化异步编程,提供更优雅的数据绑定
- 一般与西数式融合在一起,所以也会叫做:函数响应式编程(Functional Reactive Programming,简称FRP
- 比较著名的、成熟的响应式框架
- ReactiveCocoa
- 简称RAC,有Objective-C、Swift版本
- 官网: http://reactivecocoa.io/
- github: https://github.com/ReactiveCocoa
- ReactiveX
- 简称Rx,有众多编程语言的版本,比如RxJava、RxKotlin.RxJS、RxCpp、RxPHP、RxGO、RxSwift等等
- 官网:http://reactivex.io/
- github: https://github.com/ReactiveX
- ReactiveCocoa
- RxSwift
- RxSwift ( ReactiveX for Swift ) , ReactiveX 的 Swift 版本
- 源码:https://github.com/ReactiveX/RxSwift
- 中文文档:https://beeth0ven.github.io/RxSwift-Chinese-Documentation/
- RxSwift ( ReactiveX for Swift ) , ReactiveX 的 Swift 版本
- 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
- 让label绑定订阅一个定时器的
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源码分析
-
Swift于2015年正式开源,github地址:https://github.com/apple/swift
- 几个可能会经常看的目录
- docs: 一些文档
- stdlib:Swift源码
- lib:C++源码
- include:C++头文件
- 标准库源码位置
- Array分析
- Metadata分析
- 反射
- 反射是编程语言中一项强大的能力,比如Java语言的反射机制
- 对于任意一个类型,都能够动态获取这个类的所有属性和方法信息
- 对于任意一个实例,都能够动态调用它的任意方法和属性
- Swift的反射机制目前还比较弱,通过Mirror类型来提供简单的反射功能
struct Person { var age: Int = 0 var name: String = "" } let mirror = Mirror(reflecting: Person(age: 10, name: "Jack")) // struct print (mirrer.displayStyle!) // Person print(mirror.subjectType) // nil print(mirror.superclassMirror as Any) // age 10 // name Jack for case let (label?, value) in mirror.children { print(label, value) }
- 反射是编程语言中一项强大的能力,比如Java语言的反射机制
- 网络请求:https/lgithub.com/Alamofire/Alamofire
- 图片下载:https://github.com/onevcat/Kingfisher
- JSONitia: https://github.com/SwiftyJSON/SwiftyJSON
- JSON-Model转换:https://github.com/kakaopensource/KakaJSON