import UIKit
import Foundation
/函数响应式编程*****/
/// 函数式编程思想:是将操作尽可能写在一起!嵌套的函数!!
/// 本质:就是往方法里面传入Block,方法中嵌套Block调用.
/// block可以作为对象的属性,也可以作为方法的参数,也可以作为返回值。而作为返回值是链式编程的核心
/*
高阶函数是至少满足下列一个条件的函数:
1 接受一个或多个函数作为输入
2 输出一个函数
在数学中它们也叫做算子(运算符)或泛函。微积分中的导数就是常见的例子,因为它映射一个函数到另一个函数。
*/
/*
链式编程
特点:方法的返回值必须是方法的调用者
链式写法对比普通写法
*/
/// 普通写法
/*
@interface Person : NSObject
- (void)eat;
- (void)sleep;
@end
@implementation Person
-
(void)eat
{
NSLog(@"%s", FUNCTION);
} -
(void)sleep
{
NSLog(@"%s", FUNCTION);
}
@end
ViewController.m
Person person = [[Person alloc] init];
//调用时必须单个调用,而且不能任意组合顺序
/* 普通的调用方式 */
[person eat];
[person sleep];
*/
/// 链式xiefa
/*
// 链式写法
Person.h
- (Person *)eat;
- (Person *)sleep;
Person.m
-
(Person *)eat
{
NSLog(@"%s", FUNCTION);
return self;
} -
(Person *)sleep
{
NSLog(@"%s", FUNCTION);
return self;
}
ViewController.m
Person person = [[Person alloc] init];
/* 链式写法,这样不仅可以无限调用,而且可以控制顺序 */
[[person eat] sleep];
[[person sleep] eat];
[[person eat] eat];
/** 通过”点”语法,将需要执行的代码块连续的书写下去,就是链式编程.它能使代码简单易读,书写方便 */
person.eat.sleep.eat.sleep.sleep;
*/
/// 将blockly作为返回值—链式编程带参数
/*
Person.h
- (Person *(^)(NSString *food))eat3;
- (Person *(^)(NSString *where))sleep3;
Person.m
-
(Person *(^)(NSString *food))eat3
{
return ^(NSString *food) {NSLog(@"吃:%@ ",food); return self;
};
} -
(Person *(^)(NSString *where))sleep3
{
return ^(NSString *where) {NSLog(@"睡在:%@上",where); return self;
};
}
ViewController.m
Person *person = [[Person alloc] init];
/** 链式 + 函数式写法 */
person.sleep3(@"床").eat3(@"苹果").eat3(@"香蕉").sleep3(@"沙发");
返回值block不带参数,()不传参即可
person.sleep3().eat3().eat3().sleep3();
*/
/// 函数式编程
/// 函数式编程思想:是将操作尽可能写在一起!嵌套的函数!!
/// 本质:就是往方法里面传入Block,方法中嵌套Block调用.
/*
/** 返回调用者本身,获取其它属性和方法 */
-
(Person *)calculator:(NSInteger(^)(NSInteger result))block
{
_result = block(_result);return self;
}Person person = [[Person alloc] init];
/* 计算器 */
Person *calculatPerson = [person calculator:^NSInteger(NSInteger result) {result = result + 10; result = result*10; return result;
}];
NSLog(@"%ld", calculatPerson.result);
*/
/// 将block块作为函数的参数,可以异步在参数block回调,将函数运行所需要的一些信息或者产出的一些结果通过block传递。代码逻辑清晰
/// 函数响应式编程
/// 函数式
/// 特点:代码简洁(复用)、易于理解(接近自然语言)、便于代码管理
//例1:
//遍历数组(要求:1.首先获取 > 3的数字;2.获取的数字之后 + 1;3.所有数字中的偶数;4.可读性 清晰度)
let array = [1,2,3,4,5,6,7]
//普通处理方式:
for num in array{
if num > 3{
let number = num + 1
if (number % 2 == 0) {
print(number)
}
}
}
//函数式:
array.filter{ $0 > 3}
.filter{ ($0+1) % 2 == 0 }
.forEach { print($0) }
/// 响应式
/// 对象对某一数据流变化做出响应的这种编码方式称为响应式。如对象A和对象B,A和B有一种“说不清”的关系,A要时刻监控B的行为,对B的变化也做出相应的变化。那么怎么实现呢?对于B来说,B做任何事都需要向A汇报,这样A就能实时监控B的行为,并响应。在iOS开发中我们经常会响应一些事件,button、tap、textField、textView、notifaction、KVO、NSTimer等等这些,都需要做响应监听,响应后都需要在对应的响应事件中去做处理,而原生开发中,触发对象与响应方法是分离的,如button的初始化和点击响应方法是分离的。
/// 响应式编程优点
/*
1) 开发过程中,状态以及状态之间依赖过多,RAC更加有效率地处理事件流,而无需显式去管理状态。在OO或者过程式编程中,状态变化是最难跟踪,最头痛的事。这个也是最重要的一点。
2) 减少变量的使用,由于它跟踪状态和值的变化,因此不需要再申明变量不断地观察状态和更新值。
3) 提供统一的消息传递机制,将oc中的通知,action,KVO以及其它所有UIControl事件的变化都进行监控,当变化发生时,就会传递事件和值。
4) 当值随着事件变换时,可以使用map,filter,reduce等函数便利地对值进行变换操作。
*/
/*
// 1. 传统写法
//传统写法,UI代码和逻辑是分开的,为了监听一个按钮的响应事件,我们需要在另外一处地方实现。这样可读性不好,代码繁琐。
let button = UIButton()
button.addTarget(self, action: #selector(text), for: .touchUpInside)
@objc func text() {
print(“Button clicked!”)
}
// 2. Rxswift写法
//Rxswift的实现就简单多了,而且目标非常明确,就是三部曲:1创建序列,2,订阅响应消息,3.析构销毁
//当你订阅了响应消息后,只要序列发生了变化,订阅的消息总会触发,如下面的代码,当你订阅了按钮的点击事件后,每次点击按钮,订阅的消息subscibe就会收到一次。
self.button.rx.tap //序列,这里默认的序列是默认是.onTouchUpInside事件
.subscribe(onNext: { () in //订阅
print(“Button clicked!”)
}, onError: { (error) in //当Rxswift的事件链走不通,会回调这个onError,通知错误
print(“错误信息”)
}, onCompleted: {//当Rxswift订阅的所有事件链走完了,会回调这个onCompleted,告知执行完毕,这个和onError是对立互斥的,两者只会发生一个。
print(“订阅完成”)
})
.disposed(by: DisposeBag()) //销毁
*/
/// RxSwift
/*
1 什么是 ReactiveX(Reactive Extensions)
An API for asynchronous programming with observable streams
通过可观察的流实现异步编程的一种API(不明白?嗯,看完所有的例子再读一篇)
ReactiveX is more than an API, it’s an idea and a breakthrough in programming. It has inspired several other APIs, frameworks, and even programming languages.
ReactiveX 不仅仅是一种 API 那么简单,它更是一种编程思想的突破。它已经影响了其他 API,frameworks,以及编程语言。
总的一句话概括:
ReactiveX(Reactive Extensions)是通过可观察的流实现异步编程的一种API,它结合了观察者模式、迭代器模式和函数式编程的精华。RxSwift 是 ReactiveX 编程思想的一种实现
*/
/*
2 Rx的基本概念
观察者模式 Observable:
对某些数据流(很广,可以是一些事件等)进行处理,使其变成可观察对象(Observable)序列,这样观察者(observer)就可以订阅这些序列;
操作符 Operators:
然而对于订阅者来说(observer)某些选项(items)并不是自己需要的(需要过滤),某些选项(items)需要转换才能达到自己的目的;
迭代模式 Iterator:
这样集合或者序列中的值就可以进行遍历了。
调度器 Scheduler:
为了提升用户体验,或其它目的,有些操作需要放到特定的线程去执行,比如 UI 操作需要放到主线程,这就涉及到了调度器
/
/
//1:创建序列
//利用函数式编程思想,在create()构造函数中传入一个闭包,这个闭包会被类对象保存起来,后续每个时间,事件触发的时候会回调这个传入的闭包,这样就像连接了一个链条一样,顺着链条就可找到需要调用的闭包。
let ob = Observable.create { (observer) -> Disposable in
// 3:发送信号
obserber.onNext([1,2,3,4])
obserber.onCompleted()
// obserber.onError(NSError.init(domain: “error!”, code: 10087, userInfo: nil))
return Disposables.create()
//2:订阅信息
//当我们订阅了Observable的消息后,只要Observable的事件触发,都会通过OnNext这个闭包告诉我们。
let _ = ob.subscribe(onNext: { (text) in
print(“订阅到:(text)”) //这里会监听到订阅的Observable消息
}, onError: { (error) in
print(“error: (error)”) //当发生错误时,会回调这里
}, onCompleted: { // 当所有序列执行完毕时,会回调这里。
print(“完成”)
}) {
print(“销毁”)
}
*/
/*
override func viewDidLoad() {
super.viewDidLoad()
DispatchQueue.global().async {
self.from()
}
}
func from() {
Observable.from([“haha”, “kongyulu”, “cc”, “wswy”, “Rx”])
.subscribeOn(MainScheduler.instance)
.filter({ (text) -> Bool in
return text == “kongyulu”
})
.map({ (text) -> String in
return "my name is: " + text
})
.subscribe(onNext: { [weak self] (text) in
self?.nickNameLabel.text = text
})
.disposed(by: disposeBag)
}
*/
/// 1.创建序列,2,订阅序列,3,销毁序列