我想大多初始化定义的代码都能看懂,也没有叙述的必要,我主要把我以为最主要的几个部分叙述一下。react
为何先说代理。这也是以前和慎哥也说过cell里面有点击事件怎么写。(不知道这么写对不对...后面看一部分源码以后会再聊这个话题,先留坑)代理能够干什么,跨Controller传值。跨Controller调方法。git
咱们以前写代理,都是在某个Controller里的.h文件最上面建立代理。但实际上,Xcode提供了专门的Protocol文件。以前没有搞明白也是由于我以为代理必需要再某个文件里声明。github
因此,当咱们单独声明了一个Protocol文件的时候,就意味着,这个Protocol能够像一个类同样来声明变量了。mvvm
这个东西是作啥的。我只能说我解释很差,由于我没有彻底理解这个东西。我只能把我理解的说出来。ide
咱们的按钮都有一个点击事件。当点击的时候出发一个函数。函数
可是,当咱们用了RACCommand的时候,咱们的点击事件就能够这么写了。atom
self.pushBtn.rac_command = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) { NSLog(@"test signal"); return [RACSignal empty]; }];
和我以前写过的这种写法又不同了。这种写法实际上是对button addtarget那个方法的一个rac式的封装。代理
[[self.testBtn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(id x) { TestViewController *testVC = [[TestViewController alloc] init]; [self.navigationController pushViewController:testVC animated:YES]; }];
用第一种方法的缘由呢,咱们能够把点击事件赋值成为一个RACCommand类型的属性。既然能够变成一个属性了,那么就能够从新定义而且赋值。code
咱们新建一个FirstViewModel,在FirstViewModel.h中增长一个blog
@property (strong, nonatomic) RACCommand *excutePush;
而后咱们让刚刚在FirstViewController里定义的那个pushBtn的rac_command,将它赋值为FirstViewModel里的excutePush
self.pushBtn.rac_command = self.viewModel.excutePush;
这么一赋值,就达成了一个目的。按钮的事件在viewModel中执行。
须要注意的是,RACCommand的block返回的时一个signal。因此,在viewModel中,咱们要这么写
self.excutePush = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) { NSLog(@"test signal"); return [RACSignal empty]; }];
这样,咱们就实现了对点击事件的分离。
分离跳转,就要用到我开始说的代理了。
咱们作一个MVVMdemoService的代理,我放在Protocol文件夹里了。这个代理就声明了一个方法
- (void)pushViewModel:(id)viewModel;
咱们在NSLog(@"test signal");下面增长
[self.service pushViewModel:viewModel];
咱们还要实现这个代理。
在ray中的教程和雷大神的MVVMReactiveCocoa都是新建了一个Impl文件,专门用来跳转,基本思路就是navigation自己就是一个堆栈,其实全部的vc都是在navigation其中的。咱们只要控制这个这个最基本的navigation的跳转就能够了。
咱们新建一个MVVMdemoImpl文件,里面有一个初始化的方法。
- (instancetype)initWithNavigationController:(UINavigationController *)navigationController
咱们把根navigation传进去来进行逻辑跳转。
咱们在初始化的时候加上这两句核心代码。
self.demoImpl = [[MVVMdemoImpl alloc] initWithNavigationController:self.naviVC]; self.firstViewModel = [[FirstViewModel alloc] initWithService:self.demoImpl];
第一句话是声明了一个demoImpl,将navigation穿进去。
第二句话是声明了一个firstViewModel,把第一个demoImpl传了进去。这个地方的疑问在于,咱们声明的时候是
-(instancetype)initWithService:(id<MVVMdemoService>)service
参数是一个代理。咱们传的时一个NSObject类型的值。并且在MVVMdemoImpl.m中,也没有对于代理的赋值为本身。
我是这么理解的,若是有不对,还请谅解。
当咱们加入代理MVVMdemoService在MVVMdemoImpl的时候,由于MVVMdemoImpl是一个nsobject类型,而MVVMdemoService也是一个nsobject类型。因此,此时咱们的MVVMdemoImpl具备MVVMdemoService的属性了,咱们作的就是,让FirstViewModel里的service的代理便是MVVMdemoImpl。
简单的说。
就是MVVMdemoImpl == FirstViewModel.service
那么这样的话,咱们的service就能够执行MVVMdemoImpl里的pushViewModel方法了。
其实上面的最后AppDelegate的赋值代理这一块还不是很明白。有时间再说说吧。很久没写博客就想发一篇了。
以上完整代码在MVVMdemo
1.leichunfeng/MVVMReactiveCocoa
2.ReactiveCocoa Essentials: Understanding and Using RACCommand