我想大多初始化定義的代碼都能看懂,也沒有敘述的必要,我主要把我以爲最主要的幾個部分敘述一下。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