iOS開發(fā)中,我們常常將一塊View封裝起來(lái),以便于統(tǒng)一管理內(nèi)部的子控件。如iOS回顧筆記(02)中的"書"這一自定義View。
下面就來(lái)說說自定義View的封裝以及它的多種實(shí)現(xiàn)方式
自定義UIView(控件)的封裝
什么是View的封裝
如果一個(gè)View的內(nèi)部子控件比較多,一般會(huì)考慮自定義一個(gè)View,把它內(nèi)部子控件的創(chuàng)建屏蔽起來(lái),不讓外部關(guān)心。
外界傳入對(duì)應(yīng)的數(shù)據(jù)模型給view。view拿到數(shù)據(jù)模型之后給內(nèi)部的子控件設(shè)置對(duì)應(yīng)的數(shù)據(jù)。
封裝自定義控件的基本步驟
重寫
- (instancetype)initWithFrame
方法,在此方法中創(chuàng)建并添加子控件。提供一個(gè)便利的構(gòu)造方法,通常為 類方法,快速創(chuàng)建一個(gè)實(shí)例對(duì)象
重寫
- (void)layoutSubviews
方法,在此方法中設(shè)置子控件的frame,一定要調(diào)用[super layoutSubviews]
設(shè)置模型屬性,在set方法中,給對(duì)應(yīng)的子控件賦值。
看代碼
XYBookView.h 頭文件#import <UIKit/UIKit.h>@class XYBook;@interface XYBookView : UIView// 只放一個(gè)數(shù)據(jù)屬性用來(lái)賦值,內(nèi)部布局,放到.m 中自己管,不暴露給外界@property (nonatomic, strong) XYBook *book;@end實(shí)現(xiàn)文件 .m文件#import "XYBookView.h"#include "XYBook.h"@interface XYBookView ()// 兩個(gè)內(nèi)部子控件在內(nèi)部包裝起來(lái),不給外界看到@property (nonatomic, weak) UIImageView *icon;@property (nonatomic, weak) UILabel *label;@end@implementation XYBookView// 1.重寫initWithFrame:方法,創(chuàng)建子控件并添加到自己上面- (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { // 1. 創(chuàng)建書圖標(biāo) UIImageView *icon = [UIImageView new]; self.icon = icon; [self addSubview:self.icon]; // 2.書名 UILabel *bookName = [UILabel new]; bookName.textAlignment = NSTextAlignmentCenter; self.label = bookName; [self addSubview:self.label]; } return self; }// 2.重寫layoutSubviews,給自己內(nèi)部子控件設(shè)置frame- (void)layoutSubviews { [super layoutSubviews]; CGSize size = self.frame.size; self.icon.frame = CGRectMake(0, 0, size.width , size.height * 0.7); self.label.frame = CGRectMake(0, size.height * 0.7, size.width, size.height *(1 - 0.7)); }// 3.調(diào)用模型的set方法,給書的子控件賦值,- (void)setBook:(XYBook *)book { _book = book; self.icon.image = [UIImage imageNamed:book.icon]; self.label.text = book.name; }@end
以上是純代碼實(shí)現(xiàn)的View的封裝,寫起來(lái)有些麻煩。
開發(fā)中另一種常用的封裝方式是Xib,下面介紹Xib的相關(guān)知識(shí)。
XIB和Storyboard的比較
共同點(diǎn)
都是用來(lái)描述軟件界面
最后都是 Interface Builder工具來(lái)編譯
本質(zhì)上都是轉(zhuǎn)化成代碼去創(chuàng)建控件
不同點(diǎn)
Xib是輕量級(jí)的,用來(lái)描述局部的UI界面
Storyboard是重量級(jí)的,不僅可以用來(lái)描述整個(gè)應(yīng)用的多個(gè)頁(yè)面,而且可以展示頁(yè)面間的跳轉(zhuǎn)關(guān)系。
Xib的創(chuàng)建
Xib的使用
Xib的加載方式
Xib作為局部UI的描述文件,它也是一種項(xiàng)目?jī)?nèi)的資源文件,在項(xiàng)目中查找路勁也是在[UIBundle mainBundle]中,它的加載方式有兩種
方式1
在對(duì)應(yīng)的mainBundle中加載XYBookView類型的nib文件,返回是數(shù)組,取數(shù)組中對(duì)應(yīng)的view即可
NSArray *views = [[NSBundle mainBundle] loadNibNamed:@"XYBookView" owner:nil options:nil]; XYBookView *bookView = views.firstObject;
方式2
Xib/Storyboard文件編譯之后生成的都是 Nib文件,加載XYBookView.xib對(duì)應(yīng)的.nib文件,通過.nib文件實(shí)例化的數(shù)組中取到對(duì)應(yīng)的XYBookView實(shí)例對(duì)象。
UINib *nib = [UINib nibWithNibName:@"XYBookView" bundle:nil]; XYBookView *bookView = [[nib instantiateWithOwner:nil options:nil] firstObject];
使用注意
進(jìn)行類綁定,告訴Xib它是什么類型,用來(lái)描述那個(gè)文件
通常Xib文件名和要描述的文件同名,易于辨認(rèn)和管理
Xib的使用細(xì)節(jié)完善
Xib用來(lái)描述控件,是把原來(lái)代碼創(chuàng)建的內(nèi)容直接用圖形化來(lái)展示了
Xib里面的子控件需要拖線到對(duì)應(yīng)文件中,以便文件內(nèi)賦值和其他使用
封裝Xib的加載過程
#import "XYBookView.h"@interface XYBookView ()// 封裝一個(gè)快速返回實(shí)例對(duì)象的類方法+ (instancetype)bookView;@end@implementation XYBookView+ (instancetype)bookView { // 封裝Xib的加載過程 return [[NSBundle mainBundle] loadNibNamed:@"XYBookView" owner:nil options:nil].firstObject; }
小結(jié)
一個(gè)控件有兩種創(chuàng)建方式
通過代碼創(chuàng)建
初始化一定會(huì)調(diào)用
-(instancetype)initWithFrame:
方法通過Xib\StoryBoard創(chuàng)建
初始化不會(huì)調(diào)用
-(instancetype)initWithFrame:
方法,只會(huì)調(diào)用-(instancetype)initWithCoder:
方法初始化完成之后,回調(diào)用
awakeFromNib
方法
通過兩種加載方式,可以發(fā)現(xiàn):有時(shí)候我們希望在控件初始化時(shí)做一些初始化的操作,如添加子控件,設(shè)置屬性等,這時(shí)候需要根據(jù)控件的加載方式來(lái)選擇-(instancetype)initWithFrame:
,-(instancetype)initWithCoder:
,awakeFromNib
三個(gè)方法中的哪個(gè)方法進(jìn)行初始化。
踏實(shí)的學(xué)點(diǎn)東西,讓自己豐富,也讓生活豐富和充實(shí)。
分類: iOS點(diǎn)滴
標(biāo)簽: iOS開發(fā), 進(jìn)階, 回顧, 復(fù)習(xí), Xib, Storyboard, 封裝