iOS開發之利用MVVM框架來優化專案結構。對Controller瘦身以及MVC向MVVM框架的遷移。
MVC開發模式 :
1. 蘋果官方一直推薦我們開發者使用MVC的開發模式,所以我們大部分人之前的專案都是用MVC來開發APP,這樣開發,肯定會發現一個超級大的弊端,viewcontroller裡邊有大量的業務邏輯與檢視操作邏輯,隨著專案的不斷的迭代,會充斥著大量的問題,我們的單元測試也好, 我們的邏輯設計,以及程式碼的整潔性,程式碼的層級性都會出現很多的問題,為此我覺得為Controller瘦身已經是非常必要的。 也有一部分開發者著不同意這種思想,但是我們也不必固守成規,雖然MVVM想必與MVC可能從程式碼上來講並沒有減少,反而可能增加。
但是相對應的,也會帶來很多好處,下面就是MVVM 使用後的一些優點。
MVVM的優點如下:
MVVM模式和MVC模式一樣,主要目的是分離檢視(View)和模型(Model),有以下四大優點1. 低耦合。檢視(View)可以獨立於Model變化和修改,一個ViewModel可以繫結到不同的"View"上,當View變化的時候Model可以不變,當Model變化的時候View也可以不變。
2. 可重用性。你可以把一些檢視邏輯放在一個ViewModel裡面,讓很多view重用這段檢視邏輯。
3. 獨立開發。開發人員可以專注於業務邏輯和資料的開發(ViewModel),設計人員可以專注於頁面設計,使用Expression Blend可以很容易設計介面並生成xaml程式碼。
4. 可測試
下面通過程式碼來進行來進行說明
1.首先專案的層級關係圖。
1.model資料夾: 這個和mvc下的model沒有什麼區別。 一般為瘦model.
2. view資料夾: 檢視的載體, 和mvc下的view也沒有什麼區別, 由controller進行協調展示。
3. Controller資料夾 : 只包含一些檢視的操作,不包含任何的業務處理。這裡要達到瘦身的效果,經常會吧tableview 的protocal給單獨提出來,本文章將的也會把這些類給提出來,後面詳細說明
4.ViewModel: 把以前充斥在Controller中的一些業務處理放置在此地, 包含:資料請求,資料的包裝。把封裝好的資料直接傳遞給Controller直接進行顯示。 網路請求的起飛與著陸點,這個看專案的網路層架構設計。 不能一視同仁
5.TableViewProtocol資料夾: 這個就是把Tableview的資料來源與delegate給提取出來,這樣做的好處就是可以最大化的重用對應的代理方法,易於管理, 並且可以讓controller中及其的簡潔。
6.3rdLibs資料夾: 存放了一個第三方的上下拉載入控制元件。
2.完整的專案程式碼結構目錄:
下面讓我們一級一級的進行程式碼的解剖:
1.Controller程式碼解剖:
TableViewController.h
#import <UIKit/UIKit.h>
@interface TableViewController : UIViewController
@end
TableViewController.m
#import "TableViewController.h"
#import "YiRefreshHeader.h"
#import "YiRefreshFooter.h"
#import "TableViewModel.h"
#import "TableViewDataSource.h"
#import "TableViewDelegate.h"
@interface TableViewController ()
{
YiRefreshHeader *refreshHeader;
YiRefreshFooter *refreshFooter;
NSMutableArray *totalSource;
TableViewModel *tableViewModel;
UITableView *tableView;
TableViewDataSource *tableViewDataSource;
TableViewDelegate *tableViewDelegate;
}
@end
@implementation TableViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
if (iOS7) {
self.edgesForExtendedLayout = UIRectEdgeBottom | UIRectEdgeLeft | UIRectEdgeRight;
}
[email protected]"MVVMDemo With TableView";
self.view.backgroundColor=[UIColor whiteColor];
tableView=[[UITableView alloc] initWithFrame:CGRectMake(0, 0, WScreen, HScreen-64) style:UITableViewStylePlain];
[self.view addSubview:tableView];
tableViewDataSource = [[TableViewDataSource alloc] init]; //對tableview 資料來源的封裝的類
tableViewDelegate = [[TableViewDelegate alloc] init]; //對tableview 代理 封裝的類,可以方便複用
tableView.dataSource=tableViewDataSource; //把當前的tableview的資料來源指向我們的公用datasource類。
tableView.delegate=tableViewDelegate; //把當前的tableview的代理指向我們的公用的代理類。
tableViewModel=[[TableViewModel alloc] init]; //本章的重頭戲,把業務處理提出的類
totalSource=0;
// YiRefreshHeader 頭部重新整理按鈕的使用
refreshHeader=[[YiRefreshHeader alloc] init];
refreshHeader.scrollView=tableView;
[refreshHeader header];
__weak typeof(self) weakSelf = self;
refreshHeader.beginRefreshingBlock=^(){
__strong typeof(self) strongSelf = weakSelf;
[strongSelf headerRefreshAction]; //下拉重新整理
};
// 是否在進入該介面的時候就開始進入重新整理狀態
[refreshHeader beginRefreshing];
// YiRefreshFooter 底部重新整理按鈕的使用
refreshFooter=[[YiRefreshFooter alloc] init];
refreshFooter.scrollView=tableView;
[refreshFooter footer];
refreshFooter.beginRefreshingBlock=^(){
__strong typeof(self) strongSelf = weakSelf;
[strongSelf footerRefreshAction]; //上拉重新整理
};
}
// 這裡是具體的下拉重新整理方法,我們可以發現,這裡是呼叫了viewModel中的方法,並把處理的結果通過block方式返回回來。
- (void)headerRefreshAction
{
[tableViewModel headerRefreshRequestWithCallback:^(NSArray *array){
totalSource=(NSMutableArray *)array;
tableViewDataSource.array=totalSource;
tableViewDelegate.array=totalSource;
[refreshHeader endRefreshing];
[tableView reloadData];
}];
}
// 這裡是具體的上拉重新整理方法,我們可以發現,這裡是呼叫了viewModel中的方法,並把處理的結果通過block方式返回回來。
- (void)footerRefreshAction
{
[tableViewModel footerRefreshRequestWithCallback:^(NSArray *array){
[totalSource addObjectsFromArray:array] ;
tableViewDataSource.array=totalSource;
tableViewDelegate.array=totalSource;
[refreshFooter endRefreshing];
[tableView reloadData];
}];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
TableViewModel.h
#import <Foundation/Foundation.h>
typedef void (^callback) (NSArray *array);
@interface TableViewModel : NSObject
//tableView頭部重新整理的網路請求
- (void)headerRefreshRequestWithCallback:(callback)callback;
//tableView底部重新整理的網路請求
- (void)footerRefreshRequestWithCallback:(callback)callback;
@end
TableViewModel.m , 這裡應該非常的通俗易懂,就是把以前ViewController中的上下拉重新整理方法放在此地,並且通過block把處理過後的結果返回給控制器。
#import "TableViewModel.h"
#import "CustomModel.h"
@interface TableViewModel ()
@end
@implementation TableViewModel
- (instancetype)init
{
self = [super init];
if (self) {
}
return self;
}
- (void)headerRefreshRequestWithCallback:(callback)callback
{
// 後臺執行:
dispatch_async(dispatch_get_global_queue(0, 0), ^{
sleep(2);
dispatch_async(dispatch_get_main_queue(), ^{
// 主執行緒重新整理檢視
NSMutableArray *arr=[NSMutableArray array];
for (int i=0; i<16; i++) {
int x = arc4random() % 100;
NSString *string=[NSString stringWithFormat:@"下拉重新整理-測試資料%d",x];
CustomModel *model=[[CustomModel alloc] init];
model.title=string;
[arr addObject:model];
}
callback(arr);
});
});
}
- (void )footerRefreshRequestWithCallback:(callback)callback
{
// 後臺執行:
dispatch_async(dispatch_get_global_queue(0, 0), ^{
sleep(2);
dispatch_async(dispatch_get_main_queue(), ^{
// 主執行緒重新整理檢視
NSMutableArray *arr=[NSMutableArray array];
for (int i=0; i<16; i++) {
int x = arc4random() % 100;
NSString *string=[NSString stringWithFormat:@"上拉載入 -測試資料%d",x];
CustomModel *model=[[CustomModel alloc] init];
model.title=string;
[arr addObject:model];
}
callback(arr);
});
});
}
@end
TableViewDataSource.h
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface TableViewDataSource : NSObject<UITableViewDataSource>
@property (nonatomic,strong) NSArray *array;
@end
TableViewDataSource.m 把tableview的 資料來源相關的代理方法全部擰出來,以後可以進行更高的複用
#import "TableViewDataSource.h"
#import "CustomTableViewCell.h"
@implementation TableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return _array.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
if (cell == nil) {
cell = [[CustomTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell"];
}
cell.titleLabel.text=((CustomModel *)[_array objectAtIndex:indexPath.row]).title;
return cell;
}
@end
TableViewDelegate.h
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface TableViewDelegate : NSObject<UITableViewDelegate>
@property (nonatomic,strong) NSArray *array;
@end
TableViewDelegate.m
這裡我就把經常使用的tableview cell的點選代理給寫了出來,大家可以隨意進行新增其他的代理。
#import "TableViewDelegate.h"
@implementation TableViewDelegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (_array.count>0) {
UIAlertView *alert=[[UIAlertView alloc] initWithTitle:@"" message:((CustomModel *)[_array objectAtIndex:indexPath.row]).title delegate:nil cancelButtonTitle:@"sure" otherButtonTitles:nil, nil];
[alert show];
}
}
@end
其中。 model, 已經自定義的cell的具體程式碼我在這兒就不一一展示,和我們以前MVC的寫法一模一樣。
專案程式碼下載地址: 點選開啟連結
總結:
1. 利用ViewModel把業務處理操作,全部從Controller中提出,這樣在Controller中就不會充斥著大量的網路代理回撥
2. 利用封裝tableview的資料來源 與 代理 類 ,來優化大量tableview的 協議 的冗餘程式碼。減少程式碼量,方便後期維護與擴充套件。
後續:
既然我們把業務操作提取出來了。那如何展示出來,怎麼把對應的資料傳遞到view層等等,這時候就誕生了ReactiveCocoa, 雖然前期有自學過,但一直沒有理解到其精髓,只是會使用一些基本的用法,運用到專案中間來,我怕會有一些意想不到的坑, 所以不敢拿公司的利益來冒險,以後有時間。 自己寫寫demo來運用下就好。 後期再出對應的部落格詳細講解它
相關推薦
iOS開發之利用MVVM框架來優化專案結構。對Controller瘦身以及MVC向MVVM框架的遷移。
MVC開發模式 : 1. 蘋果官方一直推薦我們開發者使用MVC的開發模式,所以我們大部分人之前的專案都是用MVC來開發APP,這樣開發,肯定會發現一個超級大的弊端,viewcontroller裡邊有大量的業務邏輯與檢視操作邏輯,隨著專案的不斷的迭代,會充斥著大量的問題,我們
iOS開發之自定義導航欄返回按鈕右滑返回手勢失效的解決---親測是有效的。
問題一:怎麼自定義leftItem問題二:為什麼系統自帶的右滑返回手勢失效問題三:怎麼解決這個失效問題3.怎麼解決這個失效問題 其實很簡單很簡單~只需要新增下面這一句程式碼即可self.navigationController.interactivePopGestureRe
iOS開發之CFNetwork框架使用
iOS開發之CFNetwork框架使用 一、引言 在iOS應用開發中,CFNetwork框架其實並不是非常常用的,相對NSURLSession框架而言,這是一個相對底層的網路工作框架。官方文件中的下圖描述了CFNetwork在整個網路體系中的位置:
iOS開發之AVKit框架使用
iOS開發之AVKit框架使用 一、引言 在iOS開發框架中,AVKit是一個非常上層,偏應用的框架,它是基於AVFoundation的一層檢視層封裝。其中相關檔案和類都十分簡單,本篇部落格主要整理和總結AVKit中相關類的使用方法。 二、A
iOS開發之AddressBookUI框架詳解
iOS開發之AddressBookUI框架詳解 一、關於AddressBookUI框架 AddressbookUI是iOS開發框架中提供的一套通訊錄介面元件。其中封裝好了一套選擇聯絡人,檢視聯絡人的介面,在需要時開發者可以直接呼叫。當然對於聯絡人介面,
iOS開發之AddressBook框架詳解
iOS開發之AddressBook框架詳解 一、寫在前面 首先,AddressBook框架是一個已經過時的框架,iOS9之後官方提供了Contacts框架來進行使用者通訊錄相關操作。儘管如此,AddressBook框架依然是一個非常優雅並且使用方便的通
iOS開發之Accounts框架詳解
iOS開發之Accounts框架詳解 Accounts框架是iOS原生提供的一套賬戶管理框架,其支援Facebook,新浪微博,騰訊微博,Twitter和領英賬戶管理的功能。需要注意,在iOS 11及以上系統中,將此功能已經刪除,因此Accounts.frame
iOS開發之AssetsLibrary框架使用
iOS開發之AssetsLibrary框架使用 一、引言 AssetsLibrary框架是專門用來操作相簿相關資源的一個框架,其是iOS4到iOS9之間常使用的一個框架,在iOS9之後,系統系統了Photos框架代替了AssetsLibrary框架,但
iOS開發之AdSupport框架使用
iOS開發之AdSupport框架使用 AdSupport從字面意思上理解是用來進行廣告支援,這個框架十分簡單,裡面只有一個類,類中只有一個方法和兩個屬性。 AdSupport的唯一用途是用來獲取裝置唯一的一個廣告識別符號。可以使
iOS開發之BusinessChat框架使用
iOS開發之BusinessChat框架使用 BusinessChat是iOS11.3後引入的新框架,這個框架配合iMessage應用將商家與使用者更加緊密的結合起來,並且為商家提供了另外一種非常方便的客服系統。 &
iOS開發之優化tableView卡頓現象
1.複用單元格; 2.使用不透明的試圖,單元格中儘量少使用動畫; 3.圖片使用非同步載入同時設定圖片載入的併發數; 4.滑動時不載入圖片,滑動結束開始載入; 5.文字圖片可以直接drawInRect繪製; 6.非必要條件下,減少重新整理的cell; 7.如果ce
onvif開發之利用gSOAP生成onvif客戶端程式碼框架
cd gsoap-2.8 ./configure make sudo make install 命令列模式下敲入命令:wsdl2h -V 檢視gSOAP軟體版本,有版本出現則安裝成功。 2. 利用gSOAP生成onvif客戶端程式碼框架 2.1 在當前目錄下
ios開發之使用bundle來管理資原始檔
轉載自:http://blog.csdn.net/kylinbl/article/details/9047209 (chenyong 將資原始檔夾弄成bundle格式的特簡單單,只需要把字尾名改成.bundle即可) 在ios開發中為了方便管理資原始檔,可以使用bundl
iOS開發之ReactiveCocoa下的MVVM
最近工作比較忙,但還是出來更新部落格了,今天給大家分享一些ReactiveCocoa以及MVVM的一些東西,幹活還是比較足的。在之前發表過一篇博文,名字叫做,大體上講的就是使用Block回撥的方式實現MVVM的。在寫上篇文章時也知道有ReactiveCocoa這個函式響應式程式設計的框架,並且有許多人用它來更
iOS開發之Masonry框架原始碼解析
Masonry是iOS在控制元件佈局中經常使用的一個輕量級框架,Masonry讓NSLayoutConstraint使用起來更為簡潔。Masonry簡化了NSLayoutConstraint的使用方式,讓我們可以以鏈式的方式為我們的控制元件指定約束。本篇部落格的主題不是教你如何去使用Masonry框架的,而是
iOS開發之淺談MVVM的架構設計與團隊協作
1 // 2 // NetRequestClass.m 3 // MVVMTest 4 // 5 // Created by 李澤魯 on 15/1/6. 6 // Copyright (c) 2015年 李澤魯. All rights reserved. 7
iOS開發之ReactiveCocoa下的MVVM(乾貨分享)
最近工作比較忙,但還是出來更新部落格了,今天給大家分享一些ReactiveCocoa以及MVVM的一些東西,幹活還是比較足的。在之前發表過一篇博文,名字叫做,大體上講的就是使用Block回撥的方式實現MVVM的。在寫上篇文章時也知道有ReactiveCocoa這個函式響應式程式
iOS開發之Masonry框架-原始碼解析
Masonry是iOS在控制元件佈局中經常使用的一個輕量級框架。Masonry讓NSLayoutConstraint使用起來更為簡潔。Masonry簡化了NSLayoutConstraint的使用方式,讓我們可以以鏈式的方式為我們的控制元件指定約束。本篇是對Masonry框架的原始碼進行解析,讓你明白Maso
iOS開發之CoreSpotlight框架的應用
iOS開發之CoreSpotlight框架的應用
iOS開發之DeviceCheck框架的應用
iOS開發之DeviceCheck框架的應用 DeviceCheck框架是iOS 1