咱們在作iOS開發過程當中,靜態頁面的開發比開發動態頁面更讓咱們開發者抓狂。由於動態頁面一般是一個頁面一種cell樣式,做爲開發者只須要專一於定製好一種樣式以後,就可使用數據填充出較好的界面。而靜態cell,則可能由於一個頁面有多種cell樣式,並且頗有可能不是標準的cell樣式,須要咱們自定義,所以容易寫出來的代碼容易臃腫和重複、可讀性差。這不符合開發者的代碼優化原則(不主動重複)。我時常會由於開發這種頁面抓狂,由於會糾結到底怎麼寫會讓代碼可讀性好點,寫重複代碼的機會少點。本文就是我作過的幾個項目中總結的一套利用MVVM設計模式實現我的中心等靜態tableview界面的方法和代碼介紹,並且能夠在此基礎上不斷豐富咱們的模塊。乾貨在個人demo裏,你能夠直接拿去用。爲了你之後添加屬於本身的自定義cell,建議認真看看這篇文章。設計模式
效果展現數組
本文Demo下載地址:http://pan.baidu.com/s/1kTPucgn
再順便廣告一下:歡迎你們關注個人微信公衆號:丁丁的coding日記微信
實現思路
1.因爲我的中心或者設置模塊,使用了大量的通用Cell樣式。一般cell左邊現實圖片加文字(或者只有文字),右側則有可能有多種現實樣式(如switch開怪,箭頭,按鈕,或者文字等)。所以咱們能夠把這些通用的特性封裝成ViewModel。
2.利用ViewModel填充咱們的Cell(View)。
3.給ViewModel填充數據(Model),而後實現咱們的Cell數據和樣式展現。
實現步驟
1.ViewModel實現代碼:HooUserCenterItemModel.h
ide
#import <Foundation/Foundation.h> #import <UIKit/UIKit.h> typedef NS_ENUM(NSInteger, HooUserCenterAccessoryType) { HooUserCenterAccessoryTypeNone, // don't show any accessory view HooUserCenterAccessoryTypeDisclosureIndicator, // the same with system DisclosureIndicator HooUserCenterAccessoryTypeSwitch, // swithch }; @interface HooUserCenterItemModel : NSObject @property (nonatomic,copy) NSString *funcName; /**< 功能名稱*/ @property (nonatomic,strong) UIImage *img; /**< 功能圖片 */ @property (nonatomic,copy) NSString *detailText; /**< 更多信息-提示文字 */ @property (nonatomic,strong) UIImage *detailImage; /**< 更多信息-提示圖片 */ @property (nonatomic,assign) HooUserCenterAccessoryType accessoryType; /**< accessory */ @property (nonatomic,copy) void (^executeCode)(); /**< 點擊item要執行的代碼*/ @property (nonatomic,copy) void (^switchValueChanged)(BOOL isOn); /**< HooUserCenterAccessoryTypeSwitch下開關變化 */ @end
HooUserCenterSectionModel.h
#import <Foundation/Foundation.h> #import <UIKit/UIKit.h> @interface HooUserCenterSectionModel : NSObject @property (nonatomic,copy) NSString *sectionHeaderName; /**< 傳空表示分組無名稱*/ @property (nonatomic,assign) CGFloat sectionHeaderHeight; /**< 分組header高度*/ @property (nonatomic,strong) NSArray *itemArray; /**< item模型數組*/ @property (nonatomic,strong) UIColor *sectionHeaderBgColor; /**< 背景色*/ @end
2.Cell(View)實現代碼:
HooUserCenterCell.h #import <UIKit/UIKit.h> @class HooUserCenterItemModel; @interface HooUserCenterCell : UITableViewCell @property (nonatomic,strong) HooUserCenterItemModel *item; /**< item data*/ @end
HooUserCenterCell.m
優化
#import "HooUserCenterCell.h" #import "HooUserCenterItemModel.h" #import "UIView+XBExtension.h" #import "HooConst.h" @interface HooUserCenterCell() @property (strong, nonatomic) UILabel *funcNameLabel; @property (nonatomic,strong) UIImageView *imgView; @property (nonatomic,strong) UIImageView *indicator; @property (nonatomic,strong) UISwitch *aswitch; @property (nonatomic,strong) UILabel *detailLabel; @property (nonatomic,strong) UIImageView *detailImageView; @end @implementation HooUserCenterCell - (void)setItem:(HooUserCenterItemModel *)item { _item = item; [self updateUI]; } - (void)updateUI { [self.contentView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)]; //若是有圖片 if (self.item.img) { [self setupImgView]; } //功能名稱 if (self.item.funcName) { [self setupFuncLabel]; } //accessoryType if (self.item.accessoryType) { [self setupAccessoryType]; } //detailView if (self.item.detailText) { [self setupDetailText]; } if (self.item.detailImage) { [self setupDetailImage]; } //bottomLine UIView *line = [[UIView alloc]initWithFrame:CGRectMake(0, self.height - 1, XBScreenWidth, 1)]; line.backgroundColor = XBMakeColorWithRGB(234, 234, 234, 1); [self.contentView addSubview:line]; } -(void)setupDetailImage { self.detailImageView = [[UIImageView alloc]initWithImage:self.item.detailImage]; self.detailImageView.centerY = self.contentView.centerY; switch (self.item.accessoryType) { case HooUserCenterAccessoryTypeNone: self.detailImageView.x = XBScreenWidth - self.detailImageView.width - XBDetailViewToIndicatorGap - 2; break; case HooUserCenterAccessoryTypeDisclosureIndicator: self.detailImageView.x = self.indicator.x - self.detailImageView.width - XBDetailViewToIndicatorGap; break; case HooUserCenterAccessoryTypeSwitch: self.detailImageView.x = self.aswitch.x - self.detailImageView.width - XBDetailViewToIndicatorGap; break; default: break; } [self.contentView addSubview:self.detailImageView]; } - (void)setupDetailText { self.detailLabel = [[UILabel alloc]init]; self.detailLabel.text = self.item.detailText; self.detailLabel.textColor = XBMakeColorWithRGB(142, 142, 142, 1); self.detailLabel.font = [UIFont systemFontOfSize:XBDetailLabelFont]; self.detailLabel.size = [self sizeForTitle:self.item.detailText withFont:self.detailLabel.font]; self.detailLabel.centerY = self.contentView.centerY; switch (self.item.accessoryType) { case HooUserCenterAccessoryTypeNone: self.detailLabel.x = XBScreenWidth - self.detailLabel.width - XBDetailViewToIndicatorGap - 2; break; case HooUserCenterAccessoryTypeDisclosureIndicator: self.detailLabel.x = self.indicator.x - self.detailLabel.width - XBDetailViewToIndicatorGap; break; case HooUserCenterAccessoryTypeSwitch: self.detailLabel.x = self.aswitch.x - self.detailLabel.width - XBDetailViewToIndicatorGap; break; default: break; } [self.contentView addSubview:self.detailLabel]; } - (void)setupAccessoryType { switch (self.item.accessoryType) { case HooUserCenterAccessoryTypeNone: break; case HooUserCenterAccessoryTypeDisclosureIndicator: [self setupIndicator]; break; case HooUserCenterAccessoryTypeSwitch: [self setupSwitch]; break; default: break; } } - (void)setupSwitch { [self.contentView addSubview:self.aswitch]; } - (void)setupIndicator { [self.contentView addSubview:self.indicator]; } - (void)setupImgView { self.imgView = [[UIImageView alloc]initWithImage:self.item.img]; self.imgView.x = XBFuncImgToLeftGap; self.imgView.centerY = self.contentView.centerY; self.imgView.centerY = self.contentView.centerY; [self.contentView addSubview:self.imgView]; } - (void)setupFuncLabel { self.funcNameLabel = [[UILabel alloc]init]; self.funcNameLabel.text = self.item.funcName; self.funcNameLabel.textColor = XBMakeColorWithRGB(51, 51, 51, 1); self.funcNameLabel.font = [UIFont systemFontOfSize:XBFuncLabelFont]; self.funcNameLabel.size = [self sizeForTitle:self.item.funcName withFont:self.funcNameLabel.font]; self.funcNameLabel.centerY = self.contentView.centerY; self.funcNameLabel.x = CGRectGetMaxX(self.imgView.frame) + XBFuncLabelToFuncImgGap; [self.contentView addSubview:self.funcNameLabel]; } - (CGSize)sizeForTitle:(NSString *)title withFont:(UIFont *)font { CGRect titleRect = [title boundingRectWithSize:CGSizeMake(FLT_MAX, FLT_MAX) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName : font} context:nil]; return CGSizeMake(titleRect.size.width, titleRect.size.height); } - (UIImageView *)indicator { if (!_indicator) { _indicator = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"icon-arrow1"]]; _indicator.centerY = self.contentView.centerY; _indicator.x = XBScreenWidth - _indicator.width - XBIndicatorToRightGap; } return _indicator; } - (UISwitch *)aswitch { if (!_aswitch) { _aswitch = [[UISwitch alloc]init]; _aswitch.centerY = self.contentView.centerY; _aswitch.x = XBScreenWidth - _aswitch.width - XBIndicatorToRightGap; [_aswitch addTarget:self action:@selector(switchTouched:) forControlEvents:UIControlEventValueChanged]; } return _aswitch; } - (void)switchTouched:(UISwitch *)sw { __weak typeof(self) weakSelf = self; self.item.switchValueChanged(weakSelf.aswitch.isOn); } @end
3.最後就能夠給咱們的ViewModel添加數據,實現咱們的頁面了。實現代碼以下:
給DemoMeController.m
添加一個屬性atom
/*HooUserCenterSectionModelsection模型數組*/ @property (nonatomic,strong) NSArray *sectionArray;
給DemoMeController.m
添加一個方法,給sectionArray
添加數據spa
- (void)setupSections { //************************************section1 HooUserCenterItemModel *item1 = [[HooUserCenterItemModel alloc]init]; item1.funcName = @"個人任務1"; item1.executeCode = ^{ NSLog(@"個人任務1"); }; item1.img = [UIImage imageNamed:@"icon-list01"]; item1.detailText = @"作任務贏大獎"; item1.accessoryType = HooUserCenterAccessoryTypeDisclosureIndicator; HooUserCenterItemModel *item2 = [[HooUserCenterItemModel alloc]init]; item2.funcName = @"個人任務2"; item2.img = [UIImage imageNamed:@"icon-list01"]; item2.accessoryType = HooUserCenterAccessoryTypeDisclosureIndicator; HooUserCenterItemModel *item3 = [[HooUserCenterItemModel alloc]init]; item3.funcName = @"個人任務3"; item3.img = [UIImage imageNamed:@"icon-list01"]; item3.accessoryType = HooUserCenterAccessoryTypeDisclosureIndicator; HooUserCenterItemModel *item4 = [[HooUserCenterItemModel alloc]init]; item4.funcName = @"個人任務4"; item4.img = [UIImage imageNamed:@"icon-list01"]; item4.accessoryType = HooUserCenterAccessoryTypeDisclosureIndicator; HooUserCenterSectionModel *section1 = [[HooUserCenterSectionModel alloc]init]; section1.sectionHeaderHeight = 18; section1.itemArray = @[item1,item2,item3,item4]; HooUserCenterItemModel *item5 = [[HooUserCenterItemModel alloc]init]; item5.funcName = @"充值中心"; item5.img = [UIImage imageNamed:@"icon-list01"]; item5.executeCode = ^{ NSLog(@"充值中心"); }; item5.accessoryType = HooUserCenterAccessoryTypeDisclosureIndicator; HooUserCenterItemModel *item6 = [[HooUserCenterItemModel alloc]init]; item6.funcName = @"設置"; item6.img = [UIImage imageNamed:@"icon-list01"]; item6.executeCode = ^{ }; item6.accessoryType = HooUserCenterAccessoryTypeDisclosureIndicator; HooUserCenterSectionModel *section2 = [[HooUserCenterSectionModel alloc]init]; section2.sectionHeaderHeight = 18; section2.itemArray = @[item5,item6]; self.sectionArray = @[section1,section2]; }
使用sectionArray
數據裝配咱們的tableView的cell。設計
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *identifier = @"setting"; HooUserCenterSectionModel *sectionModel = self.sectionArray[indexPath.section]; HooUserCenterItemModel *itemModel = sectionModel.itemArray[indexPath.row]; HooUserCenterCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier]; if (!cell) { cell = [[HooUserCenterCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier]; } cell.item = itemModel; return cell; }
總結
這是咱們利用MVVM設計快速幫助咱們開發我的中心、設置等模塊。使用這個方式建立的好處,就是解放了Controller和View,讓代碼的可讀性變得更好,同時也幫助咱們封裝了一些通用模塊,將ViewModel和View與Controller解耦,方便咱們將ViewModel和View的代碼帶到其餘項目中,而且能夠擴展咱們的這ViewModel和View。code