iOS開發之有趣的UI —— 資料轉模型及MVC設計模式,iosmvc
本分享是iOS開發中有趣的UI模組的相關內容技術點分享。如果您是一位已經有C基礎了的iOS愛好者,但還未接觸Objectiov C語言,您需要學習我之前分享的 iOS開發核心語言Objective C 系列
如果您是零基礎,建議您從我之前分享的iOS開發分分鐘搞定C語言 系列開始學習。另外將無償分享自己整理出來的大概400G iOS學習視頻及學習資料,都是乾貨哦!可以新浪微博私信關注 極客James,期待與您的共同學習和探討!!由於時間有限,每天在工作之餘整理的學習分享,難免有不足之處,也希望各路大神指正!
在上一篇iOS開發之有趣的UI —— 基礎控制項與經典案例中已經對基本控制項進行了詳細的介紹並且簡單的做了一個購物車的項目,但是這個項目還有待完善,裡面還有很多非常實用技術點和設計思想,所以本次分享將從以下幾個方面進行分享。
made by 極客James
一、plist檔案
1.在學習UI控制項的時候要時刻掌握這三個基本要素:
(1)建立對象
(2)給對象設定屬性,大小,顏色,尺寸等
(3)給對象加資料
上面兩點在上一篇的分享中都已經做了詳細的分享,今天主要是對第三點給對象加資料進行分享。
2.資料存取
在iOS開發中通常資料存取有兩種方式:一種是本機資料,一種是網路資料,本機資料是存取在plist中,而網路資料是儲存在伺服器需要通過json進行解析擷取,今天主要分享本機資料的存取。
3.plist資料
(1)建立一個plist檔案
(2)在plist中寫資料
(3)將建好的的plist資料通過以下代碼匯入到檔案中
NSArray *dictArray =[NSArray arrayWithContentsOfFile:[[NSBundle mainBundle]pathForResource:@"shops" ofType:@"plist"]];// 僅僅是載入plist檔案的代碼塊
二、資料轉模型
通過自己建立一個plist檔案進行了本機資料的存取才是第一步,要想讓對象拿到資料最好的辦法是將資料轉換成模型進行使用,這樣不僅效率高還不容易出錯。
資料轉模型思路:
1.建立一個主要來處理資料的模型檔案
2.在建立好的模型檔案.h中拿到plist裡面所有的元素,並且提供一種自訂對象方法,一種構造類方法來初始化字典。
3.在模型檔案的.m中進行自訂對象方法和構造類方法的方法實現,主要目的是將字典裡面的資料取出來給模型,把資料封裝為對象的方式供使用者使用。
4.在viewController檔案中懶載入資料,並且將plist資料通過已構造好的方法進行轉化為模型。
5.在需要用到的地方,直接用對象方法或者類方法進行調用。
資料轉模型代碼實現:
1.建立了模型檔案ZJShopModel
2.在ZJShopModel.h檔案中拿到plist中的元素並且自訂初始化
// 注意:plist中有多少個屬性,這裡就要寫多少個// 商品名稱@property (nonatomic,strong)NSString *name;// 商品表徵圖@property (nonatomic,strong)NSString *icon;// 自訂對象方法的初始化- (instancetype)initWithDict:(NSDictionary *)dict;// 自訂構造類方法的初始化+ (instancetype)shopWithDict:(NSDictionary *)dict;
3.在ZJShopModel.m檔案中進行聲明的實現
// 自訂對象方法的實現- (instancetype)initWithDict:(NSDictionary *)dict{ if (self = [super init]) { // 可以通過KVC的方式直接賦值 // KVC方法 [self setValuesForKeysWithDictionary:dict]; self.name = dict[@"name"]; self.icon = dict[@"icon"]; } return self;}// 自訂構造類方法的實現+ (instancetype)shopWithDict:(NSDictionary *)dict{ return [[self alloc] initWithDict:dict];}
4.在viewController檔案中進行資料的懶載入
(1)首先要聲明一個數組
@property (strong,nonatomic)NSArray *shop;
(2)對數組進行懶載入和plist資料的模型轉化需要匯入模型標頭檔
- (NSArray *)shop{ if (_shop == nil) {// 載入plist檔案 NSArray *dictArray =[NSArray arrayWithContentsOfFile:[[NSBundle mainBundle]pathForResource:@"shops" ofType:@"plist"]];// 建立一個可變的空數組NSMutableArray *shopArray = [NSMutableArray array];// 遍曆字典 for (NSDictionary *dict in dictArray) { // 取出字典內容給模型 ZJShopModel *shop = [ZJShopModel shopWithDict:dict]; // 將轉換好的資料賦給可變數組 [shopArray addObject:shop]; } _shop = shopArray; } return _shop;}
5.在需要的地方進行調用
// 獲得index位置對應的商品資料ZJShopModel *shops = self.shop[index];
以上是plist資料轉模型的最好方法,可以達到資料的獨立管理和方便調用,在iOS開發中非常重要。
三、抽取和封裝思想
在iOS開發中,封裝和抽取思想無處不在,掌握這種思想有利用高效開發,有利於團隊合作,有利於程式擴充,所以重要性我不在闡述,直接上代碼。
在編寫代碼的時候,總會遇到重複代碼的情況,那麼做好的辦法就是將相同的代碼進行抽取,然後在分析不同之處,用傳參數的方法來解決不同,下面就來以購物車為例來分析抽取和封裝思想。
分析:
1.增加按鈕需要的相關屬性:
(1)圖片顯示狀態:Normal Highlighted Disabled
(2)按鈕的位置
(3)點擊事件
2.刪除按鈕需要的相關屬性
(1)圖片顯示狀態:Normal Highlighted Disabled
(2)按鈕的位置
(3)點擊事件
3.顯示圖片和描述的相關屬性
(1)圖片
(2)文字
(3)位置
通過分析我們可以得出刪除按鈕和增加按鈕具有一樣的屬性,只不過屬性間的內容不同,所以我們要把他們公用擁有的屬性繼續抽取並給不同的屬性進行傳值操作。
刪除按鈕和增加按鈕的方法封裝:
//將增加和刪除按鈕相同共同屬性進行抽取和封裝 - (UIButton *)addButtonWithImage:(NSString *)image hightImage:(NSString *)hightImage disableImage:(NSString *)disableImage frame:(CGRect)frame action:(SEL)action{// 初始化建立按鈕對象 UIButton *btn = [[UIButton alloc]init];// 設定按鈕背景圖片 Normal狀態 [btn setBackgroundImage:[UIImage imageNamed:image] forState:UIControlStateNormal];// 設定按鈕背景圖片 Highlighted狀態 [btn setBackgroundImage:[UIImage imageNamed:hightImage] forState:UIControlStateHighlighted]; // 設定按鈕背景圖片 Disabled狀態 [btn setBackgroundImage:[UIImage imageNamed:disableImage] forState:UIControlStateDisabled];// 設定尺寸 btn.frame = frame;// 監聽按鈕點擊 [btn addTarget:self action:action forControlEvents:UIControlEventTouchUpInside];// 將按鈕增加到視圖上 [self.view addSubview:btn]; return btn; }
抽取和封裝了增加按鈕和刪除按鈕的方法,在用的時候直接調用即可。
- (void)viewDidLoad {[super viewDidLoad];// 增加按鈕self.addBtn = [self addButtonWithImage:@"add" hightImage:@"add_highlighted"disableImage:@"add_disabled" frame:CGRectMake(30, 30, 50, 50) action:@selector(add)];// 刪除按鈕 self.removeBtn = [self addButtonWithImage:@"remove" hightImage:@"remove_highlighted"disableImage:@"remove_disabled" frame:CGRectMake(270, 30, 50, 50) action:@selector(remove)];}
四、自訂控制項
顯示物品模組的分析和封裝
物品的顯示模組是一個九宮格顯示模式,有關九宮格顯示計算可以翻閱我的上一篇分享。那麼下面就來分享下顯示物品模組的相關內容。
(1)shopView用來存放物品的視圖
’
’
(2)在shopView上顯示的九宮格
’
’
(3)在九宮格上添加資料
以上就是購物車物品顯示模組的完整過程,從中我們可以顯而易見的看出,每個格子大小寬度都一樣,就是內容不同而已,所以我們可以採用封裝的思想進行編碼。
代碼實現過程分析:
(1)通過九宮格演算法先布局好介面
(2)建立一個ZJshopView檔案專門管理九宮格顯示的視圖內容
(3)在ZJshopView中建立一個九宮格顯示的UIImageView以及UILabel和相關屬性,最好是通過對象方法或類方法在建立的時候就讓它顯示,也就是要自訂View重寫init方法等。
(4)將plist轉換的模型資料匯入到視圖中
(5)在需要的地方進行調用
代碼實現過程:
1.九宮格演算法布局介面
// 設定每個商品的尺寸 CGFloat shopW = 80; CGFloat shopH = 90; // 設定顯示的列數 int cols = 3; // 設定每一列之間的間距 CGFloat colMargin = (self.shopView.frame.size.width - cols * shopW) / (cols -1); // 設定每一行之間的間距 CGFloat rowMargin = 10; // 建立一個父控制項(用來存放圖片和文字) UIView *shopView = [[UIView alloc]init]; shopView.backgroundColor = [UIColor redColor]; // 商品的索引 NSUInteger index = self.shopView.subviews.count; // 商品的x值(取餘運算,將算出商品在第幾列) NSUInteger col = index % cols; CGFloat shopX = col * (shopW + colMargin); // 商品的y值(除法運算,將算出商品在第幾行) NSUInteger row = index / cols; CGFloat shopY = row * (shopH + rowMargin); shopView.frame = CGRectMake(shopX, shopY, shopW, shopH); // 將九宮格添加到視圖上 [self.shopView addSubview:shopView];
2.建立ZJshopView來專門管九宮格視圖內容
ZJshopView.h檔案中
注意:在自訂初始化init方法之前系統會自動調用initWithFrame方法,所以為了嚴謹起見最好自訂初始化initWithFrame,達到初始化時第一個就調用且只調用一次的效果。
@interface ZJshopView ()@property (nonatomic,weak) UIImageView *iconView;@property (nonatomic , weak)UILabel *label;@end@implementation ZJShopView// 自訂view 初始化initWithFrame- (instancetype)initWithFrame:(CGRect)frame{ if (self = [super initWithFrame:frame]){ UIImageView *iconView = [[UIImageView alloc]init]; [self addSubview:iconView]; // 添加文字 UILabel *label = [[UILabel alloc]init]; label.font = [UIFont systemFontOfSize:11]; label.textAlignment = NSTextAlignmentCenter; [self addSubview:label]; } return self;}
3.設定九宮格裡面顯示圖片和文字的位置
注意:在重寫layoutSubviews方法時一定要先調用父類也就是[super layoutSubviews];
- (void)layoutSubviews{ [super layoutSubviews]; CGFloat showH = self.frame.size.height; CGFloat showW = self.frame.size.width; self.iconView.frame = CGRectMake(0, 0, showW, showH); self.label.frame = CGRectMake(0, showW, showW, showH - showW);}
4.模型資料匯入到九宮格內容的視圖中
實現思路:
九宮格的視圖現在獨立在ZJshopView中,而資料我也已經通過資料轉模型的方式獨立到一個ZJShopModel檔案中了,那麼現在要給視圖給資料,顯而易見就是要讓模型中的資料賦給視圖的相應位置中。要想讓資料模型的資料給視圖那麼就要用到set方法。
代碼實現過程:
(1)將ZJShopModel.h匯入到ZJshopView.m中,然後在ZJshopView.h中拿到ZJShopModel中的屬性也就是要@class ZJShopModel;
(2)在ZJshopView.m中聲明視圖需要用到的屬性,並且賦給視圖所用到的屬性,兩個屬性名稱字最好相同
// 類擴充以下兩個對象@property (nonatomic , weak)UILabel *label;@property (nonatomic , weak)UIImageView *iconView;
// 將聲明的對象賦給視圖的中的對象 self.iconView = iconView; self.label =label;
(3)重寫set方法:將模型中的資料賦給視圖中的屬性
- (void)setShop:(ZJShopModel *)shop{ _shop = shop; self.iconView.image = [UIImage imageNamed:shop.icon]; self.label.text = shop.name;}
5.在需要的時候直接建立對象,在初始化的時候獲得所需要的所有屬性,達到封裝的目的,一切OK.
// 在適當的位置掉用以下方法就會建立九宮格的位置以及屬性ZJShopModel *shopView = [[ZJShopModel alloc]init];// 在適當的位置掉用以下方法就會將資料給九宮格中的視圖shopView.shop = self.shop[index];
五、xib自訂控制項
xib是一種輕量級UI可視化設計工具,適用情境為在項目中需要將好多UI控制項顯示到同一個視圖上或者相同的視圖具有同樣的屬性只是位置不同。
上面分析的購物車符合用xib方式來建立的應用情境,下面就來分析下如何採用xib的方式來實現純程式碼實現的效果。
1.建立xib
’
’
2.給xib命名為ZJShopView
’
3.建立ZJShopView工程檔案並繼承UIView
4.讓xib繼承ZJShopView,並且給xib設定視圖屬性
5.將xib中的控制項和ZJShopView建立關係
6.在ZJShopView.h中匯入資料模型通過set方法進行資料的傳遞
@class ZJShopmodel;@interface ZJShopView : UIView// 商品模型 @property (nonatomic, strong) ZJShopmodel *shop;+ (instancetype)shopViewWithShop:(ZJShopmodel *)shop;
7.在ZJShopView.m中進行xib視圖的載入和set方法實現
+ (instancetype)shopViewWithShop:(ZJShopmodel *)shop{// 載入xibZJShopView *shopView = [[[NSBundle mainBundle] loadNibNamed:NSStringFromClass(self) owner:nil options:nil] lastObject]; shopView.shop = shop; return shopView;}
set方法的實現
- (void)setShop:(ZJShopmodel *)shop{ _shop = shop; self.iconView.image = [UIImage imageNamed:shop.icon]; self.nameLabel.text = shop.name;}
通過xib的方法會很快捷的建立出九宮格顯示視圖的內容,不用在設定九宮格內容的尺寸等屬性。
六、MVC設計模式
以下是蘋果官方對MVC的定義和解釋
翻譯:
對於任何 iOS 應用程式而言,模型-視圖-控制器 (MVC) 都是一個優秀設計的關鍵所在。MVC 會將應用程式中的對象分配給以下三種角色中的一種:模型、視圖或者控制器。在這種模式中,模型會記錄應用程式的資料,視圖會顯示使用者介面並構成應用程式的內容,而控制器則會管理您的視圖。通過響應使用者的操作並使用內容填充視圖,控制器充當了模型和視圖二者之間通訊的通道。
通過官方的翻譯想必您已經領悟了其中的精髓所在,本篇分享中也同樣用到了MVC的設計模式和思想,例如本次分享的購物車案例。
M:ZJShopModel 資料模型
V:ZJShopView 視圖模型
C:viewController 大管家 視圖控制器
通過這種設計模式能夠很明顯的感受到開發效率的提升,分模組進行編碼,然後通過視圖控制器來進行調度,有利於程式的擴充性和易讀性。
在開發中也提倡通過MVC的設計模式去開發。
著作權聲明:本文為博主原創文章,為了能相互促進,相互學習,請關注新浪微博:極客James