使用XIB開發界面

首先聲明,我這是根據別人的講解來寫出來的,,,

一、關于xib

1.xib和nib

在程序里面我們看到的基本上是UINib這個類。xib文件可以可以被Xcode編譯成為nib文件、xib文件其實就是一個xml文件,而nib文件就是編譯后的二進制文件。

2.Xib文件的重要屬性

1.xib文件名

2.File’s Owner

3.xib文件中的視圖的Class

4.xib文件中的視圖的Outlet指向

二 、Demo演示

demo演示:GitHub - liubitao/test: test?

1.加載歐xib中File’s Owner為nil的視圖

cell1.xib

ViewController.m

- (void)loadCell1{

// cell.xib的File's Owner為nil

NSArray *views = [[NSBundle mainBundle]loadNibNamed:@"cell1" owner:nil options:nil];

self.cell1 = [views lastObject];

// 從xib加載進來的View大小是確定的,但是該視圖在父視圖中的位置是不確定的

// 此外,視圖中的子視圖也是原封不動地Load進來的

CGRect rect = _cell1.frame;

rect.origin.x += 50.0f;

rect.origin.y += 50.0f;

_cell1.frame = rect;

[self.view addSubview:_cell1];

}

運行結果:

結論: ?

??? 1).File’s Owner為nil的xib文件中的視圖屬于通用視圖,在工程中可以復用

??? 2).從xib加載進來的View大小是確定的,但是該視圖在父視圖中的位置是不確定的,因此需要開發者自行指定

??? 3).視圖中的所有子視圖會被原封不動地Load進來

2. 加載xib中File’s Owner為self的視圖

cell2.xib

viewCaontroller.m

.......

@property (strong, nonatomic) IBOutlet UIView *cell2;

.......

- (void)loadCell2{

// cell2.xib的File's Owner設為self,并建立了一個從該xib的View到self的IBOutlet cell2

[[NSBundle mainBundle] loadNibNamed:@"cell2" owner:self options:nil];

// 只要self主動調用Load XIB的方法,self持有的IBOutlet指向的視圖就會被初始化

// 這里不需要通過views[0]的方式存取視圖

CGRect rect = _cell2.frame;

rect.origin.x = _cell1.frame.origin.x;

rect.origin.y = _cell1.frame.origin.y + 80.0f;

_cell2.frame = rect;

[self.view addSubview:_cell2];

}

運行結果:

結論:

????? 1).File’s Owner不為nil的xib文件中的視圖屬于專用視圖,在工程中不應該被復用

????? 2).只要self主動調用loadNibNamed:owner:options:方法,self持有的IBOutlet指向的視圖就會被初始化

????? 3).存取xib中的視圖不用views[0]的方式,而是通過IBOutlet類型的property進行存取

3. 加載xib中File’s Owner為特定類的視圖

cell3.xib

Cell3View.h

@interface Cell3View : UIView

@property (strong, nonatomic) IBOutlet UIView *cellView3;

@end

ViewController.m

...

@property (nonatomic,strong) Cell3View *cell3;

...

- (void)loadCell3{

// cell3.xib的File's Owner是Cell3類的實例,并建立了一個從該xib的View到Cell3實例的IBOutlet

// 只要通過_cell3主動調用Load XIB的方法,該IBOutlet指向的視圖就會被初始化

self.cell3 = [[Cell3View alloc]init];

[[NSBundle mainBundle] loadNibNamed:@"cell3" owner:_cell3 options:nil];

UIView *view = _cell3.cellView3;

CGRect rect = view.frame;

rect.origin.x = _cell1.frame.origin.x;

rect.origin.y = _cell2.frame.origin.y + 80.0f;

view.frame = rect;

[self.view addSubview:view];

}

運行結果:

結論:

????? 1).File’s Owner類可以封裝視圖中的各種邏輯,而不僅僅是提供視圖內容

????? 2).只要通過File’s Owner類主動調用loadNibNamed:owner:options:方法,該IBOutlet指向的視圖就會被初始化

4. 加載xib中文件名和視圖類名一致的視圖(File’s Owner為nil)

Cell4.xib

Cell4.h

@interface Cell4 : UIView

+ (instancetype)viewFromNIB;

@property (weak, nonatomic) IBOutlet UILabel *titleLabel;

@end

Cell4.m

+ (instancetype)viewFromNIB {

// 加載xib中的視圖,其中xib文件名和本類類名必須一致

// 這個xib文件的File's Owner必須為空

// 這個xib文件必須只擁有一個視圖,并且該視圖的class為本類

NSArray *views = [[NSBundle mainBundle] loadNibNamed:NSStringFromClass([self class]) owner:nil options:nil];

return views[0];

}

- (void)awakeFromNib {

// 視圖內容布局

self.backgroundColor = [UIColor yellowColor];

self.titleLabel.textColor = [UIColor whiteColor];

}

運行結果:


結論:

這里的viewFromNib方法只是對loadNibNamed:owner:options:方法的一個簡單封裝,要求的條件包括: -xib文件名和本類類名必須一致 - 這個xib文件的File’s Owner必須為空 -這個xib文件必須只擁有一個視圖,并且該視圖的class為本類

5. 通過UIViewController的initWithNibName:bundle:方法加載xib文件中的視圖

cell5.xib

如果Cell5ViewController類希望self.view就是xib文件中的View,可以在Connections頁中建立view -> File’s Owner的Outlet,如下:

Cell5ViewController.h/m

@interface Cell5ViewController : UIViewController

@property (weak, nonatomic) IBOutlet UILabel *titleLabel;

@end

@implementation Cell5ViewController

- (void)viewDidLoad {

[super viewDidLoad];

self.view.backgroundColor = [UIColor blackColor];

self.titleLabel.textColor = [UIColor whiteColor];

}

ViewController.m

...

@property (nonatomic,strong) Cell5ViewController *cell5VC;

...

- (void)loadCell5{

//加載控制器

self.cell5VC = [[Cell5ViewController alloc] initWithNibName:@"cell5" bundle:[NSBundle mainBundle]];

UIView *cell5 = _cell5VC.view;

CGRect rect = cell5.frame;

rect.origin.x = _cell4.frame.origin.x;

rect.origin.y = _cell4.frame.origin.y + 80.0f;

cell5.frame = rect;

[self.view addSubview:cell5];

}

運行結果:

結論:

將xib的File’s Owner設成一個UIViewController子類,可以將這個xib文件的視圖展示和外部響應事件(例如點擊一個按鈕觸發的點擊事件,該視圖的手勢事件等)全部封裝在一個ViewController中,如果把按鈕的點擊事件封裝在一個UIView類中,貌似破壞了MVC模式,因此最好將xib的File’s Owner設成一個UIViewController子類,該類可以通過 addChildViewController方法將其添加到現有的ViewController上。如果只是希望加載視圖,可以通過viewcontroller.view存取。

如果希望ViewControllerA加載并響應aXIBView中的按鈕點擊事件,這時必須建立一個aXIBView到ViewControllerA的IBAction,如果ViewControllerA需要擁有多個這樣的XIB,那么ViewControllerA會變得非常的龐大,此時可以通過為每一個XIB設置一個ViewController,再讓ViewControllerA加載這些Child ViewControllers,這樣可以將這些事件的響應職責和視圖的描繪工作分派給專門的Child ViewController,在減小ViewControllerA體積的同時,也可以提高各個xib的可復用性。

??? 這里的viewControllerFromNIB方法其實就是initWithNibName:bundle:方法的一個簡單封裝,要求:xib的File’s Owner設為本類。

6. 通過UIViewController+NIB加載xib文件中的View Controller類和其視圖

cell6.xib

UIViewController+NIB.h/m

@interface UIViewController (NIB)

//?要求xib文件名和View?Controller類名一致

+?(instancetype)loadFromNib;

@end

@implementation?UIViewController?(NIB)

+ (instancetype)loadFromNib {

// [self class]會由調用的類決定

Class controllerClass = [self class];

NSLog(@"class = %@", controllerClass);

return [[controllerClass alloc] initWithNibName:@"cell6" bundle:[NSBundle mainBundle]];

}

@end

Cell6ViewController.h/m

@interface Cell6ViewController : UIViewController

@property (weak, nonatomic) IBOutlet UILabel *titleLabel;

@property (weak, nonatomic) IBOutlet UIButton *action;

@end

@implementation Cell6ViewController

- (void)viewDidLoad {

[super viewDidLoad];

self.view.backgroundColor = [UIColor grayColor];

self.titleLabel.text = @"Gray View";

self.titleLabel.textColor = [UIColor whiteColor];

self.titleLabel.textAlignment = NSTextAlignmentCenter;

self.titleLabel.font = [UIFont systemFontOfSize:8.5f];

[self.action setTitle:@"action" forState:UIControlStateNormal];

[self.action setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];

}

// 推薦從XIB文件中加載View Controller的方法,這種方法可以將XIB文件中的視圖和其按鈕響應事件全部封裝在Cell6ViewController

// 如果Cell6ViewController的按鈕響應事件由ViewController作出響應,那么二者的耦合度就過高

// 建議:

// 單純的通用View展示,使用從xib文件加載視圖的方法,File's Owner設為nil

// 特定擁有者的View展示,從xib文件加載視圖時,File's Owner設為擁有者

// 如果視圖中有按鈕響應事件,或其它可以和用戶交互的事件,建議采用從XIB文件中加載View Controller的方法,這樣可以封裝UI展示和交互事件

- (IBAction)action:(id)sender{

NSLog(@"action");

}

ViewController.m

...

@property (nonatomic,strong) Cell6ViewController *cell6VC;

...

- (void)loadCell6{

self.cell6VC = [Cell6ViewController loadFromNib];

UIView *cell6 = _cell6VC.view;

UIView *cell5 = _cell5VC.view;

CGRect rect = cell6.frame;

rect.origin.x = cell5.frame.origin.x;

rect.origin.y = cell5.frame.origin.y + 80.0f;

cell6.frame = rect;

[self.view addSubview:cell6];

}

運行結果:

結論:

這里我專門寫了一個UIViewController+NIB的category,只需要調用loadFromNib類方法就可以加載xib中的視圖。(我的示例中的xib的名字和控制器的名字是不一樣的,你可以弄成一樣的,讓后使用NSStringFromClass(controllerClass)來通用加載就可以了)要求: - xib文件的File’s Owner必須設置為對應的View Controller類。

三、總結

在寫界面時同時混用xib和代碼可以提高效率,而對xib的使用主要體現在其專用性和通用性上。

注意:在xib中可以有多個視圖控件,但是從xib中load出來的是一個數組,那么怎么來確定哪個對象對應的是哪個控件呢?

。。。。。。。。結論。。。。。。。。。。。

從xib中load出來的views數組中視圖對象的排列順序和xib 左邊的對象排列順序一致(其實就是xml文件中元素的排序而已),在下圖的位置。。。。。)(雖然我只有一個對象,,,當然我的目的是告訴大家是在那個地方!!!!)

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,967評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,273評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,870評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,742評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,527評論 6 407
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,010評論 1 322
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,108評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,250評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,769評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,656評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,853評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,371評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,103評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,472評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,717評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,487評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,815評論 2 372

推薦閱讀更多精彩內容