iOS開發(fā)中,我們常常將一塊View封裝起來,以便于統(tǒng)一管理內(nèi)部的子控件。如iOS回顧筆記(02)中的"書"這一自定義View。

下面就來說說自定義View的封裝以及它的多種實(shí)現(xiàn)方式

自定義UIView(控件)的封裝

什么是View的封裝

  • 如果一個(gè)View的內(nèi)部子控件比較多,一般會(huì)考慮自定義一個(gè)View,把它內(nèi)部子控件的創(chuàng)建屏蔽起來,不讓外部關(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ù)屬性用來賦值,內(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)部包裝起來,不給外界看到@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的封裝,寫起來有些麻煩。

開發(fā)中另一種常用的封裝方式是Xib,下面介紹Xib的相關(guān)知識(shí)。

XIB和Storyboard的比較

共同點(diǎn)

  • 都是用來描述軟件界面

  • 最后都是 Interface Builder工具來編譯

  • 本質(zhì)上都是轉(zhuǎn)化成代碼去創(chuàng)建控件

不同點(diǎn)

  • Xib是輕量級(jí)的,用來描述局部的UI界面

  • Storyboard是重量級(jí)的,不僅可以用來描述整個(gè)應(yīng)用的多個(gè)頁面,而且可以展示頁面間的跳轉(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它是什么類型,用來描述那個(gè)文件

  • 通常Xib文件名和要描述的文件同名,易于辨認(rèn)和管理

Xib的使用細(xì)節(jié)完善

  • Xib用來描述控件,是把原來代碼創(chuàng)建的內(nè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ù)控件的加載方式來選擇-(instancetype)initWithFrame:-(instancetype)initWithCoder:,awakeFromNib三個(gè)方法中的哪個(gè)方法進(jìn)行初始化。

http://www.cnblogs.com/xiaoyouPrince/p/6499133.html