淺談MVC和MVVM架構(gòu)模式(二)

首先我們來建立一個項目,以MVC模式和MVVM模式分別展示一個簡單tableview.

Paste_Image.png

1.AppGeneral:通用類

a.Base:基類(整個框架的基類,使用需要繼承)

b.Categories : 公共擴(kuò)展類 (就是一些常用的類別)

c.Macro:宏定義類 (就是整個應(yīng)用會用到的宏定義)
1):AppMacro.h -- app項目的相關(guān)宏定義
2):NotificationMacro.h -- 通知相關(guān)的宏定義
2):ApiMacro.h -- 項目中測試環(huán)境和生產(chǎn)環(huán)境所有接口路徑的宏定義

d.Models: 公共Model (公用的一些數(shù)據(jù)模型)

e.Utils:項目的相關(guān)工具類(比如類似數(shù)據(jù)請求等工具類)

f.Views:公共View (封裝的一些常用的View)

2.Main:項目中主要的東西(如AppDelegate,main.m)

3.Modules:模塊 (如首頁模塊,發(fā)現(xiàn)模塊,我的模塊等)

4.Resource:這里放置的是工程所需的一些資源(Fonts 字體,Images 圖片,Sounds 聲音,Videos 視頻)

5.Vendors : 第三方的類庫/SDK,(UMeng、baiduMapSDK等等)斗锭。

接下來進(jìn)入正題

1.MVC模式

Paste_Image.png
@interface ProductModel : NSObject

 @property (copy, nonatomic) NSString *desc;  //描述

@end
@interface ProductCell : UITableViewCell

 @property (strong, nonatomic) ProductModel *productModel;

 + (instancetype)cellForTableView:(UITableView *)tableView;

@end

@interface ProductCell ()

 @property (strong, nonatomic) UILabel *descLbl;

@end

@implementation ProductCell

+ (instancetype)cellForTableView:(UITableView *)tableView
{
    NSString *identify = @"ProductCell";
    ProductCell *cell = [tableView dequeueReusableCellWithIdentifier:identify];
    if (nil == cell) {
        cell = [[ProductCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identify];
    }
    return cell;
}

- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
        
        self.selectionStyle = UITableViewCellSelectionStyleNone;
        
        self.descLbl = [[UILabel alloc] init];
    
        [self.contentView addSubview:self.descLbl];
        
    }
    return self;
}

-(void)layoutSubviews
{
    [super layoutSubviews];
    
    [self.descLbl mas_makeConstraints:^(MASConstraintMaker *make) {
       
        make.edges.equalTo(self.contentView).with.insets(UIEdgeInsetsMake(10, 10, 10, 10));
    }];
}

-(void)setProductModel:(ProductModel *)productModel
{
    self.descLbl.text = productModel.desc;
}

@end

@interface ProductsVC ()<UITableViewDelegate,UITableViewDataSource>

 @property (strong, nonatomic) UITableView *productListTableView;

 @property (strong, nonatomic) NSMutableArray *productsArray;

@end

@implementation ProductsVC

- (void)viewDidLoad {
   
    [super viewDidLoad];
    
    [self setupUI];
    
    [self setupUILayout];
    
    [self requestData];
    
}

-(void)setupUI
{
    self.productListTableView = [[UITableView alloc] init];
    self.productListTableView.delegate = self;
    self.productListTableView.dataSource = self;
    [self.view addSubview:self.productListTableView];
}

-(void)setupUILayout
{
     [self.productListTableView mas_makeConstraints:^(MASConstraintMaker *make) {
        
         make.left.equalTo(self.view);
         make.top.equalTo(self.view);
         make.right.equalTo(self.view);
         make.bottom.equalTo(self.view);
     }];
}

-(void)requestData
{
    [NetWorkManager requestWithType:HttpRequestTypeGet withUrlString:@"/test" withParaments:@{@"page":@"1"} withSuccessBlock:^(NSDictionary *object) {
        
        if ([[object valueForKey:@"success"] boolValue]) {
            
            self.productsArray = [ProductModel mj_objectArrayWithKeyValuesArray:[object valueForKey:@"data"]];
            
            [self.productListTableView reloadData];
            
        }else{
            
            NSLog(@"%@",[object valueForKey:@"errorMsg"]);
        }

        
    } withFailureBlock:^(NSError *error) {
        
        NSLog(@"系統(tǒng)忙,請稍后再試");
        
    } progress:^(float progress) {
        
    }];
}

#pragma mark-- tableDelegate,tableDataSource

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.productsArray.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    ProductCell *cell = [ProductCell cellForTableView:tableView];
    
    ProductModel *productModel = self.productsArray[indexPath.row];
    
    cell.productModel = productModel;
    
    return cell;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return 50;
}


#pragma mark--  懶加載
-(NSMutableArray *)productsArray
{
    if (_productsArray==nil) {
        
        _productsArray = [NSMutableArray array];
        
    }
    return _productsArray;
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    
}

@end

這就完成了一個非常簡單列表的MVC模式,當(dāng)然,隨著頁面的復(fù)雜程度,你會發(fā)現(xiàn)控制器會越來越臃腫,這就是MVC模式非常大的一個弊端.

最后我們來看看MVVM+RAC模式是怎樣完成這么一個簡單的列表頁面(這里就不細(xì)講RAC的使用了) cell和model代碼不變,變的是控制器里面的代碼和新增的一個vm

@interface ProductViewModel : NSObject<UITableViewDataSource>

 //請求命令
 @property (strong, nonatomic) RACCommand *reuqesCommand;

 //模型數(shù)組
 @property (strong, nonatomic) NSArray *modelArray;

@end

@implementation ProductViewModel

- (instancetype)init
{
    if (self = [super init]) {
        
        [self initialBind];
    }
    return self;
}


-(void)initialBind
{
    _reuqesCommand = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
        
        return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
            
            [NetWorkManager requestWithType:HttpRequestTypePost withUrlString:@"/test" withParaments:@{@"page":@"1"} withSuccessBlock:^(NSDictionary *object) {
                
                if ([[object valueForKey:@"success"] boolValue]) {
                    
                    // 請求成功調(diào)用
                    // 把數(shù)據(jù)用信號傳遞出去
                    [subscriber sendNext:[ProductModel mj_objectArrayWithKeyValuesArray:[object valueForKey:@"data"]]];
                    
                    [subscriber sendCompleted];
                    
                }else{
                    
                    NSLog(@"%@",[object valueForKey:@"errorMsg"]);
                }

                
            } withFailureBlock:^(NSError *error) {
                
            } progress:^(float progress) {
                
            }];
            
            return nil;
            
        }];
        
    }];
}

#pragma mark - UITableViewDataSource

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.modelArray.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    ProductCell *cell = [ProductCell cellForTableView:tableView];
    
    ProductModel *productModel = self.modelArray[indexPath.row];
    
    cell.productModel = productModel;
    
    return cell;
}

@end

@interface ProductListVC ()

 @property (strong, nonatomic) UITableView *productListTableView;

 @property (strong, nonatomic) ProductViewModel *productViewModel;

@end

@implementation ProductListVC

- (void)viewDidLoad {
    
    [super viewDidLoad];
    
    [self setupUI];
    
    [self setupUILayout];
    
    [self bindViewModel];
}

-(void)setupUI
{
    self.productListTableView = [[UITableView alloc] init];
    self.productListTableView.dataSource = self.productViewModel;
    [self.view addSubview:self.productListTableView];
}

-(void)setupUILayout
{
    [self.productListTableView mas_makeConstraints:^(MASConstraintMaker *make) {
        
        make.left.equalTo(self.view);
        make.top.equalTo(self.view);
        make.right.equalTo(self.view);
        make.bottom.equalTo(self.view);
    }];
}

-(void)bindViewModel
{
    //執(zhí)行請求
    RACSignal *requesSiganl = [self.productViewModel.reuqesCommand execute:nil];
    
    //獲取請求數(shù)據(jù)
    [requesSiganl subscribeNext:^(NSArray *x) {
        
        self.productViewModel.modelArray = x;
        
        [self.productListTableView reloadData];
        
    }];
}


#pragma mark -- 懶加載
-(ProductViewModel *)productViewModel
{
    if (_productViewModel==nil) {
        
        _productViewModel = [[ProductViewModel alloc] init];
        
    }
    
    return _productViewModel;
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末宰闰,一起剝皮案震驚了整個濱河市垒迂,隨后出現(xiàn)的幾起案子局待,更是在濱河造成了極大的恐慌绰姻,老刑警劉巖亡问,帶你破解...
    沈念sama閱讀 219,539評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件官紫,死亡現(xiàn)場離奇詭異,居然都是意外死亡州藕,警方通過查閱死者的電腦和手機(jī)束世,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評論 3 396
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來床玻,“玉大人毁涉,你說我怎么就攤上這事⌒馑溃” “怎么了贫堰?”我有些...
    開封第一講書人閱讀 165,871評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長馅精。 經(jīng)常有香客問我严嗜,道長,這世上最難降的妖魔是什么洲敢? 我笑而不...
    開封第一講書人閱讀 58,963評論 1 295
  • 正文 為了忘掉前任漫玄,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘睦优。我一直安慰自己渗常,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,984評論 6 393
  • 文/花漫 我一把揭開白布汗盘。 她就那樣靜靜地躺著皱碘,像睡著了一般。 火紅的嫁衣襯著肌膚如雪隐孽。 梳的紋絲不亂的頭發(fā)上癌椿,一...
    開封第一講書人閱讀 51,763評論 1 307
  • 那天,我揣著相機(jī)與錄音菱阵,去河邊找鬼踢俄。 笑死,一個胖子當(dāng)著我的面吹牛晴及,可吹牛的內(nèi)容都是我干的都办。 我是一名探鬼主播,決...
    沈念sama閱讀 40,468評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼虑稼,長吁一口氣:“原來是場噩夢啊……” “哼琳钉!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起蛛倦,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤歌懒,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后溯壶,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體歼培,經(jīng)...
    沈念sama閱讀 45,850評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,002評論 3 338
  • 正文 我和宋清朗相戀三年茸塞,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片查剖。...
    茶點(diǎn)故事閱讀 40,144評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡钾虐,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出笋庄,到底是詐尸還是另有隱情效扫,我是刑警寧澤,帶...
    沈念sama閱讀 35,823評論 5 346
  • 正文 年R本政府宣布直砂,位于F島的核電站菌仁,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏静暂。R本人自食惡果不足惜济丘,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,483評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧摹迷,春花似錦疟赊、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至鲫寄,卻和暖如春吉执,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背地来。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評論 1 272
  • 我被黑心中介騙來泰國打工戳玫, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人靠抑。 一個月前我還...
    沈念sama閱讀 48,415評論 3 373
  • 正文 我出身青樓量九,卻偏偏與公主長得像,于是被迫代替她去往敵國和親颂碧。 傳聞我的和親對象是個殘疾皇子荠列,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,092評論 2 355

推薦閱讀更多精彩內(nèi)容