1. 程式人生 > >MVVM模式初體驗(使用ReactiveCocoa獲取網路資料)

MVVM模式初體驗(使用ReactiveCocoa獲取網路資料)

使用RAC也有一段時間了,由於此前的專案都是使用的MVC模式,網路請求都封裝在固定的模組中,抽取出來十分不方便,所以到目前為止並沒有涉及到使用RAC去做獲取網路請求的情景。
近期,著手重構目前手上的專案,準備給臃腫的Controller瘦身,MVVM貌似是一個不錯的選擇(既然使用了RAC,那為什麼不使用MVVM呢?)。於是,開始上手體驗MVVM模式和RAC的結合使用(RAC的基礎知識在這就不介紹了,百度一下,一大推老司機都有分享)。不用不知道,一用才發現RAC和MVVM簡直是絕配啊,那體驗真是改變了我對程式設計的傳統觀念(函式響應式程式設計真心好用)。
這裡用一個小demo來舉例:
進入頁面載入資料顯示。這裡使用我當前專案中的一個介面來模擬資料。既然是MVVM,那Model和ViewModel肯定是少不了的。如下:我們新建一個ViewModel叫LoadStoreViewModel(因為這裡是載入商店資料),傳統的MVC模式中,網路請求都是在ViewController中完成的,這裡我們把網路請求封裝到對應的ViewModel中去,能夠有效的減少ViewController的負擔,降低耦合性。
LoadStoreViewModel主要有三個屬性:statues(網路載入狀態),code1(編號),以及儲存資料的陣列dataArry,還有一個載入資料訊號loadDataSignal;
初始化loadDataSignal:(主要進行網路請求)

//
- (RACSignal *)loadDataSignal{
    if (_loadDataSignal==nil) {
        AFHTTPRequestOperationManager *manager=[AFHTTPRequestOperationManager manager];
        manager.requestSerializer=[[AFJSONRequestSerializer alloc]init];
        NSDictionary *params[email protected]{@"code1":@"MWG08A09"};
        _loadDataSignal=[manager rac_GET:kLoadURL parameters:params
]; } return _loadDataSignal; }

呼叫loadDataSignal處理網路請求結果:


-(void)initWithSubscrible{
    [[self.loadDataSignal deliverOn:[RACScheduler mainThreadScheduler]] subscribeNext:^(RACTuple *jsonDataResult) {
        //請求成功,載入資料
        NSDictionary *tuple=[jsonDataResult objectAtIndex:0];
        NSArray
*resultList=tuple[@"resultList"]; if (resultList.count>0) { self.dataArray=[[[resultList.rac_sequence map:^id(NSDictionary *dataSource) { NSDictionary *dic=[(NSDictionary *)dataSource mutableCopy]; WGStoreModel *model=[WGStoreModel mj_objectWithKeyValues:dic]; return model; }] array] mutableCopy]; } }]; //請求失敗 [self.loadDataSignal subscribeError:^(NSError *error) { self.statues[email protected]"沒有網路,哈哈"; }]; }

ViewModel的操作完成,接下來要在Controller中繫結ViewModel
繫結ViewModel,初始化,然後監聽ViewModel中的網路請求狀態,獲得ViewMode中網路請求結果,在Controller中給出相應的提示,資料載入成功,顯示資料重新整理控制元件:

-(void)bindViewModel{
    @weakify(self);
    self.storeViewModel=[[LoadStoreViewModel alloc]init];
    self.isLoading=YES;
    self.code1=kCode1;
    RAC(self.storeViewModel,code1)=RACObserve(self, code1);

    //載入狀態
   [RACObserve(self, isLoading) subscribeNext:^(id x) {
        UIApplication.sharedApplication.networkActivityIndicatorVisible = [x boolValue];
   }];

    //載入網路資料成功
    [[[RACObserve(self.storeViewModel, dataArray) ignore:nil] doNext:^(id x) {
        self.isLoading=YES;
    }] subscribeNext:^(id x) {
        @strongify(self);
        self.isLoading=NO;
        //重新整理控制元件--
        [self.tableView reloadData];
    }];

    //載入網路資料失敗
    [[RACObserve(self.storeViewModel, statues) filter:^BOOL(id value) {
        //filter是過濾
        return value !=nil;
    }] subscribeNext:^(NSString *str) {
        UIAlertView *alertView=[[UIAlertView alloc]initWithTitle:@"提示" message:str delegate:self cancelButtonTitle:@"confirm" otherButtonTitles:nil, nil];
        [alertView show];
    }];

}

ViewController中初始化TableView;

- (UITableView *)tableView{
    if (!_tableView) {
        _tableView=[[UITableView alloc]initWithFrame:CGRectZero style:UITableViewStylePlain];
        _tableView.delegate=self;
        _tableView.dataSource=self;
        _tableView.showsVerticalScrollIndicator=NO;
        _tableView.rowHeight=49;
    }
    return _tableView;
}

tableView的資料來源和協議方法實現

#pragma mark -tableView DataSource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
    return 1;
}

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return [self.storeViewModel.dataArray count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    static NSString *[email protected]"CELL";
    UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:indefier];
    if (!cell) {
        cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:indefier];;
    }
    WGStoreModel *model=self.storeViewModel.dataArray[indexPath.row];
    cell.textLabel.text=model.shopName;

    return cell;
}

相關推薦

MVVM模式體驗使用ReactiveCocoa獲取網路資料)

使用RAC也有一段時間了,由於此前的專案都是使用的MVC模式,網路請求都封裝在固定的模組中,抽取出來十分不方便,所以到目前為止並沒有涉及到使用RAC去做獲取網路請求的情景。 近期,著手重構目前手上的專案,準備給臃腫的Controller瘦身,MVVM貌似是

zTree體驗一)——小試牛刀

插件 root tracking per margin 接受 dsm 獲取 實現 zTree 是一個依靠 jQuery 實現的多功能 “樹插件”。優異的性能、靈活的配置、多種功能的組合是 zTree 最大長處。 ——zTree官網 zTree v3

git系列1之安裝體驗windows)

conf pan cnblogs it管理 png 下一步 rac -1 stage 1.百度雲盤地址 https://pan.baidu.com/s/1o8vAt78 2.下載後雙擊直接下一步下一步即可 3.創建一個目錄,並在目錄中創建文件README.CD 4.

跟著小甲魚學算法之算法體驗1)

-a 這就是 網上 clas 序列 系列 n) bsp col   從網上下載了小甲魚的算法與數據結構視頻,打算把這個系列跟著視頻學完。以達到對算法有初步的了解 什麽是算法?   算法是解決特定問題求解步驟的描述,在計算機中表現為指令的有限序列,並且每條指條表示一個或者

redis 之體驗window)

程序 rdl ssi set onf 解釋 -c 控制 edi 1 下載window版本的redis :https://github.com/MSOpenTech/redis/releases 2 解壓壓縮包。我的放在了E盤: E:/redis 3 程序,輸入cmd

ansible-playbook劇本體驗二)

地址 ans 服務 環境 mar restart sts 修改配置 劇本 實驗目的: 通過ansible劇本對被管理端進行部署httpd服務,並且修改配置文件,啟動服務。 操作環境 操作系統 IP地址 角色 Centos7 192.168.71.129 ans

watchOS 開發 - 體驗使用 IB 新增 Label)

編譯環境 一、建立專案 二、查看錶盤,新增label 三、連線 四、InterfaceController apple Watch啟動原理 五、問題 六、

Spring Boot 體驗9)使用thymeleaf

  步驟:在pom.xml中引入thymeleaf <dependency> <groupId>org.springframework.boot</groupId> <artifactId>sp

Spring Boot 體驗10)使用使用freemarker

一:在pom.xml中引入freemarker <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boo

SSM整合開發實戰-poi匯入匯出excel-mvc三層模式開發體驗福利:內附完整視訊教程)

    前面幾篇部落格雖然簡單的介紹了基於SSM的框架實現POI匯入匯出的介紹,但是也就只是“簡單的介紹”而已,而且沒有物盡其用。即整合出來的SSM其實還可以做其他很多的事情,閒暇之餘我又基於SSM開發了“產品資訊”的“增加 刪除 修改 更新”功能,目的是為了體會體會目前企業

Qt體驗二)

QT初體驗(二) 1.視窗跳轉   想到視窗跳轉的實現方式,應該很容易想到新建開啟新的視窗,然後關閉當前視窗   首先我們得新建一個視窗的類,然後在當前類中建立這個類的物件,呼叫Show()函式顯示出新視窗,close()函式關閉當前視窗   實現的方式大概就是下面這個樣子: ui2 = ne

docker筆記之體驗容器管理)

容器基本操作: 建立一個容器 [[email protected] ~]# docker run -itd ubuntu 3635f4dd3ae30a4377fc4f2eafc191b7890bbe5873bb4e5f9e5077f794466ec4 檢視容器

go語言體驗流程控制、range遍歷、函式、結構體、面向物件)

一、流程控制 // main package main import ( "fmt" ) func main() { x := 2 switch x { case 1: fmt.Print("beifeng 1") case 2:

go語言體驗流程控制、range遍歷、函數、結構體、面向對象)

需要 3.3 fmt float compute 捕獲異常 value 地址 異常處理 一、流程控制 // main package main import ( "fmt" ) func main() { x := 2 switch x {

IDEA+SpringBoot MyBatis Dynamic SQL的體驗一)

ybatis generator在2017年12月釋出了version 1.3.6,在該版本添加了新的TargetRuntime:   MyBatis Dynamic SQL(mybatis 動態SQL)     Mybatis Dynamic Sql與以前TargetRuntime相

IDEA+SpringBoot MyBatis Dynamic SQL的體驗一)

key dynamics table force exec tst ron annotate time ybatis generator在2017年12月發布了version 1.3.6,在該版本添加了新的TargetRuntime:   MyBatis Dynamic S

Vue-Cli3體驗一)

  前段時間看到一篇關於vue-cli3的文章,看到和老版本的vue-cli有很大的區別,就自己試試踩踩坑。 vue cli是一個基於Vue.js進行快速開發的完整系統。 它通過@vue/cli的方式搭建互動式的專案腳手架 它通過@vue/cli + @vue/cli-se

Vue-Cli3體驗二)

CLI服務   CLI 服務 (@vue/cli-service) 是一個開發環境依賴。它是一個 npm 包,區域性安裝在每個 @vue/cli 建立的專案中。CLI 服務是構建於 webpack 和 webpack-dev-server 之上的。它包含了: 載入其它 CLI

mysql 體驗 -----資料和欄位的增刪改查)

上篇隨筆說到了如何去安裝和 DOS命令 一些最簡單的操作,以及如何去鍵一個數據庫和如何建表。   這次接著來談mysql 裡資料和欄位的增刪改查 有增刪改查就會有資料型別以及資料型別的屬性 mysql資料型別和資料屬性有很多,先接觸一些最基本和最實用的的。   mysql 資料

Vue體驗五)過濾器的使用

Vue.js 允許你自定義過濾器,被用作一些常見的文字格式化。使用格式為: <!-- 在兩個大括號中 -->{{ me