乐虎游戏|乐虎国际登录|欢迎你

计算机iOS-ReactiveCocoa学习笔记1

日期:2020-04-15编辑作者:计算机资讯

①. 简化响应式函数的模式

在Swift中,我们有几种响应式的开发模式:target-action、代理、通知中心、KVO等。以上每个模式对应的场景不同,我们需要根据场景选择合适的模式。RAS的整合了所有的模式的特点,开辟了一套事件流-观察者的模式,将以上种种模式替代。

一篇关于RectiveCocoa的总结文档

1.ReactiveCocoa常见操作方法介绍。

②.高度聚集的代码实现

我们使用闭包的原因 -- 将相关代码在同一环境中实现异步执行,提升代码的可读性。RAS将这种思想用到极致。

百度搜索了一下RectiveCocoa,都是与MVVM关联在一起。

1.1 ReactiveCocoa操作须知

③. 与MVVM设计模式结合使用写出优雅简洁的代码

简化MVC中因项目逐渐庞大导致Controller中代码的沉冗,MVVM模式被我们喜欢,但是它带来的另一个问题是V和VM(viewModel)之间的数据传递过于复杂。而RAS的数据绑定解决了这个问题,我们使用这两者的结合,能够写出很优雅的代码。

RAC-Signal就 RAC 来说是构造单元. 它代表我们最终将要收到的信息. 当你能将未来某时刻收到的消息具体表示出来时,你可以开始预先运用逻辑并构建你的信息流,而不是必须等到事件发生.

信号会为了控制通过应用的信息流而获得所有这些异步方法(委托, 回调 block, 通知, KVO, target/action 事件观察, 等)并将它们统一到一个接口下.这只是直观理解. 不仅是这些, 因为信息会流过你的应用, 它还提供给你轻松转换/分解/合并/过滤信息的能力.

1·简述下MVVM

所有的信号(RACSignal)都可以进行操作处理,因为所有操作方法都定义在RACStream.h中,因此只要继承RACStream就有了操作处理方法。1.2 ReactiveCocoa操作思想

信号:

计算机 1信号

信号是一个发送一连串值的物体. 但是我们这儿的信号啥也不干, 因为它还没有订阅者. 如果有订阅者监听时信号才会发信息. 它将会向那个订阅者发送0或多个载有数值的”next”事件, 后面跟着一个”complete”事件或一个”error”事件. (信号类似于其他语言/工具包中的 “promise”, 但更强大, 因为它不仅限于向它的订阅者一次只传递一个返回值. )

计算机 2

正如我之前提到的, 如果觉得需要的话你可以过滤, 转换, 分解和合并那些值. 不同的订阅者可能需要使用信号通过不同方式发送的值.

计算机 3

MVC:ModelViewViewController

运用的是Hook思想,Hook是一种用于改变API(应用程序编程接口:方法)执行结果的技术.Hook用处:截获API调用的技术。Hook原理:在每次调用一个API返回结果之前,先执行你自己的方法,改变结果的输出。1.3 ReactiveCocoa核心方法bind

MVVM:ModelViewView-Model

ReactiveCocoa操作的核心方法是bind,而且RAC中核心开发方式,也是绑定,之前的开发方式是赋值,而用RAC开发,应该把重心放在绑定,也就是可以在创建一个对象的时候,就绑定好以后想要做的事情,而不是等赋值之后在去做事情。

信号的由来:

计算机,信号是一些等待某事发生的异步代码, 然后把结果值发送给它们的订阅者. 你可以用RAC-Signal的类方法createSignal或者手动创建信号:

在这里用一个具有成功和失败 block 的网络操作创建了一个信号. (如果我想让信号在被订阅时才让网络请求发生, 还可以用RACSignal的类方法defer. )我在成功的 block 里使用提供的subscriber对象调用sendNext:和sendCompleted:方法, 或在失败的 block 中调用sendError:. 现在我可以订阅这个信号并将在响应返回时接收到 json 值或是 error.

RACSignal *usernameValidSignal = RACObserve(self. viewModel, usernameIsValid);

计算机 4创建信号

Model:容纳表现数据-模型对象信息的结构体,并在一个单独的管理类中维护的创建/管理模型的统一逻辑。

列如:把数据展示到控件上,之前都是重写控件的setModel方法,用RAC就可以在一开始创建控件的时候,就绑定好数据。

View:包含实际 UI 本身(不论是 UIView 代码, storyboard 和 xib), 任何视图特定的逻辑, 和对用户输入的反馈. 在 iOS 中这不仅需要 UIView 代码和那些文件, 还包括很多需由 UIViewController 处理的工作。

在开发中很少使用bind方法,bind属于RAC中的底层方法,RAC已经封装了很多好用的其他方法,底层都是调用bind,用法比bind简单.

订阅者:

订阅者就是一段代码, 它等待信号给它发送一些值, 然后订阅者就能处理这些值了. (它也可以作用于 “complete” 和 “error” 事件. )

这有一个简单的订阅者, 是通过向信号的实例方法subscribeNext传入一个 block 来创建的. 我们在这通过RACObserve()宏创建信号来观察一个对象上属性的当前值, 并把它赋值给一个内部属性

- viewDidLoad {

// . . . // create and get a reference to the signal

RACSignal *usernameValidSignal = RACObserve(self. viewModel, isUsernameValid);

// update the local property when this value changes

[usernameValidSignal subscribeNext: ^(NSNumber *isValidNumber) { self. usernameIsValid = isValidNumber. boolValue }];}

注意: RAC 只处理对象, 而不处理像BOOL这样的原始值. 不过不用担心, RAC 通常会帮你这些转换.

幸运的是 RAC 的创造者也意识到这种绑定行为的普遍必要性, 所以他们提供了另一个宏RAC(). 与RACObserve()相同, 你提供想要与即将到来的值绑定的对象和参数, 在其内部它所做的是创建一个订阅者并更新其属性的值. 我们的例子现在看起来像这样:

- viewDidLoad {

RAC(self, usernameIsValid) = RACObserve(self. viewModel, isUsernameValid);

}

View-Model:

bind方法简单介绍和使用。// 假设想监听文本框的内容,并且在每次输出结果的时候,都在文本框的内容拼接一段文字“输出:”

转换数据流

RAC 为我们提供的用于转换数值流的方法. 我们将会利用RACSignal的实例方法map.

我们将 view-model 上的isUsernameValid发生的变化直接绑定到goButton的enabled属性上. 对alpha的绑定更酷, 因为我们正在使用map方法将值转换成与alpha属性相关的值. (注意在这里我们返回的是一个NSNumber对象而不是原始float值. 这基本上是唯一的污点: 你需要负责为 RAC 将原始值转化为对象, 因为它不能帮你导出来.

订阅信号链时要明白重要的一件事是每当一个新值通过信号链被发送出去时, 实际上会给每个订阅者都发送一次. 直到意识到这就我们而言是有意义的, 信号发出的值不存储在任何地方(除了 RAC 在内部实现中). 当信号需要发送一个新的值时, 它会遍历所有的订阅者并给每个订阅者发送那个值.

这为什么重要?这意味着信号链某处存在的任何副作用, 任何影响应用世界的转变, 将会发生多次. 这对新接触 RAC 的用户来说是意想不到的. (这也违反了函数式构建的理念-数据输入, 数据输出).

一个做作的例子可能是: 信号链某处的信号在每次按钮被按下时更新self中的一个计数器属性. 如果信号链有多个订阅者, 计数器的增长将会比你想的还要多. 你需要努力从信号链中尽可能剔除副作用. 当副作用不可避免时, 你可以使用一些恰当的预防机制

除副作用之外, 你需要注意带有昂贵操作和可变数据的信号链. 网络请求就是一个三者兼得的例子:

a. 网络请求影响了应用的网络层.

b. 网络请求为信号链引入了可变数据. (两个完全一样请求可能返回了不同的数据. )

c. 网络请求反应慢

1、作为一个表现视图显示自身所需数据的静态模型;

// 方式一:在返回结果后,拼接。 [_textField.rac_textSignal subscribeNext:^ { NSLog(@"输出:%@",x); }];// 方式二:在返回结果前,拼接,使用RAC中bind方法做处理。// bind方法参数:需要传入一个返回值是RACStreamBindBlock的block参数// RACStreamBindBlock是一个block的类型,返回值是信号,参数(value,stop),因此参数的block返回值也是一个block。// RACStreamBindBlock:// 参数一:表示接收到信号的原始值,还没做处理// 参数二:用来控制绑定Block,如果*stop = yes,那么就会结束绑定。// 返回值:信号,做好处理,在通过这个信号返回出去,一般使用RACReturnSignal,需要手动导入头文件RACReturnSignal.h。// bind方法使用步骤:// 1.传入一个返回值RACStreamBindBlock的block。// 2.描述一个RACStreamBindBlock类型的bindBlock作为block的返回值。// 3.描述一个返回结果的信号,作为bindBlock的返回值。// 注意:在bindBlock中做信号结果的处理。// 底层实现:// 1.源信号调用bind,会重新创建一个绑定信号。// 2.当绑定信号被订阅,就会调用绑定信号中的didSubscribe,生成一个bindingBlock。// 3.当源信号有内容发出,就会把内容传递到bindingBlock处理,调用bindingBlock(value,stop)// 4.调用bindingBlock(value,stop),会返回一个内容处理完成的信号(RACReturnSignal)。// 5.订阅RACReturnSignal,就会拿到绑定信号的订阅者,把处理完成的信号内容发送出来。// 注意:不同订阅者,保存不同的nextBlock,看源码的时候,一定要看清楚订阅者是哪个。// 这里需要手动导入#import <ReactiveCocoa/RACReturnSignal.h>,才能使用RACReturnSignal。[[_textField.rac_textSignal bind:^RACStreamBindBlock{ // 什么时候调用: // block作用:表示绑定了一个信号. return ^RACStream *(id value, BOOL *stop){ // 什么时候调用block:当信号有新的值发出,就会来到这个block。 // block作用:做返回值的处理 // 做好处理,通过信号返回出去. return [RACReturnSignal return:[NSString stringWithFormat:@"输出:%@",value]]; };}] subscribeNext:^ { NSLog;}];

Tweetboat Plus

让我们着眼于如何用 ReactiveCocoa 将 view-model 与视图控制器连接起来:

- viewDidLoad {

[super viewDidLoad];

RAC(self. viewModel, username) = [myTextfield rac_textSignal];

RACSignal *usernameIsValidSignal = RACObserve(self. viewModel, usernameValid);

RAC(self. goButton, alpha) = [usernameIsValidSignal map: ^(NSNumber *valid) { return valid. boolValue ? @1 : @0. 5; }];

RAC(self. goButton, enabled) = usernameIsValidSignal;

RAC(self. avatarImageView, image) = RACObserve(self. viewModel, userAvatarImage);

RAC(self. userNameLabel, text) = RACObserve(self. viewModel, userFullName);

@weakify;

[[[RACSignal merge: @[RACObserve(self. viewModel, tweets), RACObserve(self. viewModel, allTweetsLoaded)]] bufferWithTime: 0 onScheduler: [RACScheduler mainThreadScheduler]] subscribeNext: ^ { @strongify; [self. tableView reloadData]; }];

[[self. goButton rac_signalForControlEvents: UIControlEventTouchUpInside] subscribeNext: ^ { @strongify; [self. viewModel getTweetsForCurrentUsername]; }];

}

-(UITableViewCell*)tableView: (UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath {

// if table section is the tweets section

if (indexPath. section == 0) { MYTwitterUserCell *cell = [self. tableView dequeueReusableCellWithIdentifier: @"MYTwitterUserCell" forIndexPath: indexPath];

// grab the cell view model from the vc view model and assign it

cell. viewModel = self. viewModel. tweets[indexPath. row];

return cell;

} else {

// else if the section is our loading cell

MYLoadingCell *cell = [self. tableView dequeueReusableCellWithIdentifier: @"MYLoadingCell" forIndexPath: indexPath];

[self. viewModel loadMoreTweets];

return cell;

}

}

// MYTwitterUserCell

// this could also be in cell init

- awakeFromNib {

[super awakeFromNib];

RAC(self. avatarImageView, image) = RACObserve(self, viewModel. tweetAuthorAvatarImage);

RAC(self. userNameLabel, text) = RACObserve(self, viewModel. tweetAuthorFullName);

RAC(self. tweetTextLabel, text) = RACObserve(self, viewModel. tweetContent);

}

RAC(self.viewModel, username) = [myTextfield rac_textSignal];

在这我们用 RAC 库中的方法从UITextField拉取一个信号. 这行代码将 view-model 上的可读写属性username绑定到文本框上的用户输入的任何更新.

RACSignal *usernameIsValidSignal = RACObserve(self. viewModel, usernameValid);

RAC(self. goButton, alpha) = [usernameIsValidSignal map: ^(NSNumber *valid) { return valid. boolValue ? @1 : @0. 5; }];

RAC(self. goButton, enabled) = usernameIsValidSignal;

在这我们用RACObserve方法在 view-model 的usernameValid属性上创建了一个信号usernameIsValidSignal. 无论何时属性发生变化, 它将会沿着管道发送一个新的@YES或@NO. 我们拿到那个值并将其绑定到goButton的两个属性上. 首先我们将alpha分别对应 YES 或 NO 更新到1或0. 5(记着在这必须返回NSNumber). 然后我们直接将信号绑定到enabled属性, 因为 YES 和 NO 在这无需转换就能完美地运作.

RAC(self. avatarImageView, image) = RACObserve(self. viewModel, userAvatarImage);

RAC(self. userNameLabel, text) = RACObserve(self. viewModel, userFullName);

参考资料: ReactiveCocoa和MVVM入门

2、收集, 解释和转换那些数据;

1.4ReactiveCocoa操作方法之映射(flattenMap,Map)

收集:网络请求,control控制的数值变更;

flattenMap,Map用于把源信号内容映射成新的内容。flattenMap简单使用

解释:赋值;

// 监听文本框的内容改变,把结构重新映射成一个新值.

转换:viewmodel内的逻辑运算;

// flattenMap作用:把源信号的内容映射成一个新的信号,信号可以是任意类型。

3、目的:让view(controller)的任务更清晰,就是展示view-Model提供的数据。

// flattenMap使用步骤:// 1.传入一个block,block类型是返回值RACStream,参数value// 2.参数value就是源信号的内容,拿到源信号的内容做处理// 3.包装成RACReturnSignal信号,返回出去。// flattenMap底层实现:// 0.flattenMap内部调用bind方法实现的,flattenMap中block的返回值,会作为bind中bindBlock的返回值。// 1.当订阅绑定信号,就会生成bindBlock。// 2.当源信号发送内容,就会调用bindBlock(value, *stop)// 3.调用bindBlock,内部就会调用flattenMap的block,flattenMap的block作用:就是把处理好的数据包装成信号。// 4.返回的信号最终会作为bindBlock中的返回信号,当做bindBlock的返回信号。// 5.订阅bindBlock的返回信号,就会拿到绑定信号的订阅者,把处理完成的信号内容发送出来。[[_textField.rac_textSignal flattenMap:^RACStream * { // block什么时候 : 源信号发出的时候,就会调用这个block。 // block作用 : 改变源信号的内容。 // 返回值:绑定信号的内容. return [RACReturnSignal return:[NSString stringWithFormat:@"输出:%@",value]];}] subscribeNext:^ { // 订阅绑定信号,每当源信号发送内容,做完处理,就会调用这个block。 NSLog;}];

Summary:Model不变,view不变,增加View-Model分担ViewController的责任(每个view将有自己的view-model来约束)

Map简单使用:// 监听文本框的内容改变,把结构重新映射成一个新值.

其最终结果就是MVMCV

// Map作用:把源信号的值映射成一个新的值// Map使用步骤:// 1.传入一个block,类型是返回对象,参数是value// 2.value就是源信号的内容,直接拿到源信号的内容做处理// 3.把处理好的内容,直接返回就好了,不用包装成信号,返回的值,就是映射的值。// Map底层实现:// 0.Map底层其实是调用flatternMap,Map中block中的返回的值会作为flatternMap中block中的值。// 1.当订阅绑定信号,就会生成bindBlock。// 3.当源信号发送内容,就会调用bindBlock(value, *stop)// 4.调用bindBlock,内部就会调用flattenMap的block// 5.flattenMap的block内部会调用Map中的block,把Map中的block返回的内容包装成返回的信号。// 5.返回的信号最终会作为bindBlock中的返回信号,当做bindBlock的返回信号。// 6.订阅bindBlock的返回信号,就会拿到绑定信号的订阅者,把处理完成的信号内容发送出来。 [[_textField.rac_textSignal map:^id { // 当源信号发出,就会调用这个block,修改源信号的内容 // 返回值:就是处理完源信号的内容。 return [NSString stringWithFormat:@"输出:%@",value];}] subscribeNext:^ { NSLog;}];

关于View-Model

FlatternMap和Map的区别

不对视图控制器起作用,或通告其变化

1.FlatternMap中的Block返回信号。2.Map中的Block返回对象。3.开发中,如果信号发出的值不是信号,映射一般使用Map4.开发中,如果信号发出的值是信号,映射一般使用FlatternMap。总结:signalOfsignals用FlatternMap。

关于ViewController

// 创建信号中的信号RACSubject *signalOfsignals = [RACSubject subject];RACSubject *signal = [RACSubject subject];

1、不再发起网络服务调用

[[signalOfsignals flattenMap:^RACStream * { // 当signalOfsignals的signals发出信号才会调用 return value;}] subscribeNext:^ { // 只有signalOfsignals的signal发出信号才会调用,因为内部订阅了bindBlock中返回的信号,也就是flattenMap返回的信号。 // 也就是flattenMap返回的信号发出内容,才会调用。 NSLog(@"%@aaa",x);}];// 信号的信号发送信号[signalOfsignals sendNext:signal];// 信号发送内容[signal sendNext:@1];

2、不再管理数组(类似tableview的dataSource)

1.5 ReactiveCocoa操作方法之组合。concat:按一定顺序拼接信号,当多个信号发出的时候,有顺序的接收信号。RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {

3、不再判断某些值是否有效

 [subscriber sendNext:@1]; [subscriber sendCompleted]; return nil;}];RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { [subscriber sendNext:@2]; return nil;}];// 把signalA拼接到signalB后,signalA发送完成,signalB才会被激活。RACSignal *concatSignal = [signalA concat:signalB];// 以后只需要面对拼接信号开发。// 订阅拼接的信号,不需要单独订阅signalA,signalB// 内部会自动订阅。// 注意:第一个信号必须发送完成,第二个信号才会被激活[concatSignal subscribeNext:^ { NSLog;}];// concat底层实现:// 1.当拼接信号被订阅,就会调用拼接信号的didSubscribe// 2.didSubscribe中,会先订阅第一个源信号// 3.会执行第一个源信号的didSubscribe// 4.第一个源信号didSubscribe中发送值,就会调用第一个源信号订阅者的nextBlock,通过拼接信号的订阅者把值发送出来.// 5.第一个源信号didSubscribe中发送完成,就会调用第一个源信号订阅者的completedBlock,订阅第二个源信号这时候才激活。// 6.订阅第二个源信号,执行第二个源信号的didSubscribe// 7.第二个源信号didSubscribe中发送值,就会通过拼接信号的订阅者把值发送出来.

4、其实就是不再管text或者image是什么了

then:用于连接两个信号,当第一个信号完成,才会连接then返回的信号。// then:用于连接两个信号,当第一个信号完成,才会连接then返回的信号// 注意使用then,之前信号的值会被忽略掉.// 底层实现:1、先过滤掉之前的信号发出的值。2.使用concat连接then返回的信号[[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {

5、只管view-Model中的变化

 [subscriber sendNext:@1]; [subscriber sendCompleted]; return nil;}] then:^RACSignal *{ return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { [subscriber sendNext:@2]; return nil; }];}] subscribeNext:^ { // 只能接收到第二个信号的值,也就是then返回信号的值 NSLog;}];

Summary:将view-model与view关联,通过修改view model中的值的变更来修改view中的数值变化;ViewController就只能老老实实的管view-model的数值变更就好了。

merge:把多个信号合并为一个信号,任何一个信号有新值的时候就会调用.// merge:把多个信号合并成一个信号//创建多个信号RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {

2·ReactiveCocoa

 [subscriber sendNext:@1]; return nil;}];RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { [subscriber sendNext:@2]; return nil;}];// 合并信号,任何一个信号发送数据,都能监听到.RACSignal *mergeSignal = [signalA merge:signalB];[mergeSignal subscribeNext:^ { NSLog;}];// 底层实现:// 1.合并信号被订阅的时候,就会遍历所有信号,并且发出这些信号。// 2.每发出一个信号,这个信号就会被订阅// 3.也就是合并信号一被订阅,就会订阅里面所有的信号。// 4.只要有一个信号被发出就会被监听。

解决View和View-Model关联的问题

zipWith:把两个信号压缩成一个信号,只有当两个信号同时发出信号内容时,并且把两个信号的内容合并成一个元组,才会触发压缩流的next事件。RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {

举例

 [subscriber sendNext:@1]; return nil;}];RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { [subscriber sendNext:@2]; return nil;}];// 压缩信号A,信号BRACSignal *zipSignal = [signalA zipWith:signalB];[zipSignal subscribeNext:^ { NSLog;}];// 底层实现:// 1.定义压缩信号,内部就会自动订阅signalA,signalB// 2.每当signalA或者signalB发出信号,就会判断signalA,signalB有没有发出个信号,有就会把最近发出的信号都包装成元组发出

假设这是一个登陆页面,我要判断用户名是否合法,密码是否匹配,这些在MVC的情况下我都会在Controller中进行判断,是的话会怎么怎么样,不是的话会怎么怎么样。

combineLatest:将多个信号合并起来,并且拿到各个信号的最新的值,必须每个合并的signal至少都有过一次sendNext,才会触发合并的信号。RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {

而在MVVM和RectiveCocoa的帮助下,我们可以使用一个登陆的ViewModel,所有的判断和结果我可以写在ViewModel中。而在Controller中我只要1、关联用户名的text和viewmodel中的username,密码对应。2、就不用管TA了。

 [subscriber sendNext:@1]; return nil;}];RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { [subscriber sendNext:@2]; return nil;}];// 把两个信号组合成一个信号,跟zip一样,没什么区别RACSignal *combineSignal = [signalA combineLatestWith:signalB];[combineSignal subscribeNext:^ { NSLog;}];// 底层实现:// 1.当组合信号被订阅,内部会自动订阅signalA,signalB,必须两个信号都发出内容,才会被触发。// 2.并且把两个信号组合成元组发出。

RectiveCocoa的学习

reduce聚合:用于信号发出的内容是元组,把信号发出元组的值聚合成一个值RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {

概念,一直是我不想去背却又不得不背的东西。

 [subscriber sendNext:@1]; return nil;}];RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { [subscriber sendNext:@2]; return nil;}];// 聚合// 常见的用法,。combineLatest:(id<NSFastEnumeration>)signals reduce:reduceBlock// reduce中的block简介:// reduceblcok中的参数,有多少信号组合,reduceblcok就有多少参数,每个参数就是之前信号发出的内容// reduceblcok的返回值:聚合信号之后的内容。

1、RACSignal:RAC的构造单元,代表我们最终收到的信息,(当你能将未来某事某刻接收到的消息具体表示出来,我们可以预先运用逻辑构建信息流,而不是等到事件发生)

RACSignal *reduceSignal = [RACSignal combineLatest:@[signalA,signalB] reduce:^id(NSNumber *num1 ,NSNumber *num2){

简述:

 return [NSString stringWithFormat:@"%@ %@",num1,num2];

1、信号是基本单位,也是写完代码会接收到的东西,因为是数据关联在view和view-model上,我们可以提前将需要展示出来的数据在viewmodel中处理了,再通过关联影响view的值的变化。而不是在controller中书写了。(个人理解,如有偏差,请各种指正)

}];

2、信号会为了控制通过应用的信息流而获得所有这些异步方法(委托, 回调 block, 通知, KVO, target/action 事件观察, 等)并将它们统一到一个接口下.这只是直观理解. 不仅是这些, 因为信息会流过你的应用, 它还提供给你轻松转换/分解/合并/过滤信息的能力.

[reduceSignal subscribeNext:^ { NSLog;}];// 底层实现:// 1.订阅聚合信号,每次有内容发出,就会执行reduceblcok,把信号内容转换成reduceblcok返回的值

简述:中央集权制,信号中处理这些传值方式;并通过书写的逻辑达到预期的效果。

1.6 ReactiveCocoa操作方法之过滤。

信号如何将ViewModel与View关联上

filter:过滤信号,使用它可以获取满足条件的信号.

信号是一个发送一连串值的物体。需要在订阅者监听时信号才会发信息,信号会向订阅者发送0或多个带有数值的’next’事件,后面带有’complete’或’error’。

// 过滤:// 每次信号发出,会先执行过滤条件判断.[_textField.rac_textSignal filter:^BOOL(NSString *value) {return value.length > 3;}];

(信号类似于其他语言/工具包中的“promise”(1),但更强大,因为它不仅限于向它的订阅者一次只传递一个返回值. )

ignore:忽略完某些值的信号.

1、创建一个信号

// 内部调用filter过滤,忽略掉ignore的值[[_textField.rac_textSignal ignore:@"1"] subscribeNext:^ {

RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id subscriber) {

return nil;

}];

NSLog;}];distinctUntilChanged:当上一次的值和当前的值有明显的变化就会发出信号,否则会被忽略掉。

2、信号中添加订阅者接收到的东西

// 过滤,当上一次和当前的值不一样,就会发出内容。// 在开发中,刷新UI经常使用,只有两次数据不一样才需要刷新[[_textField.rac_textSignal distinctUntilChanged] subscribeNext:^ {

RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id subscriber) {

NSLog;}];take:从开始一共取N次的信号

//以下为新加

// 1、创建信号RACSubject *signal = [RACSubject subject];

NSString *str=[NSString stringWithFormat:@"];

NSURL *url = [NSURL URLWithString:[str stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];

NSURLRequest *request = [NSURLRequest requestWithURL:url];

AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc]init];

[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {

[subscriber sendNext:@""];

[subscriber sendCompleted];

} failure:^(AFHTTPRequestOperation *operation, NSError *error) {

[subscriber sendError:error];

}];

[operation start];

//end

return nil;

}];

// 2、处理信号,订阅信号[[signal take:1] subscribeNext:^ {

本文由乐虎游戏发布于计算机资讯,转载请注明出处:计算机iOS-ReactiveCocoa学习笔记1

关键词:

计算机在iOS开垦中应用Protobuf

Protobuf简介 protocolbuffer 是google的一种数据交换的格式,它独立于语言,独立于平台。google提供了多种语言的实现:j...

详细>>

Android 滚轮选择器的实现详解

之前项目中需要实现这样一个功能,效果如图所示: 简介 最近用一个日期选择控件,感觉官方的DatePicker操作有点复杂...

详细>>

深入剖析Objective-C中的Swizzle

method_name是函数的选择器,method_type是参数和返回值类型编码的c字符串,method_imp是指向实际函数的函数指针。可以通过下...

详细>>

Atitit.收银系统pos 以及打印功能的行业标准

OG视讯直播,Atitit.收银系统pos以及打印功能的行业标准 之前公司有个面向商户的项目,需要连接商户打印机打印小票...

详细>>