xib模塊化設計

Swift之xib模塊化設計

轉發:http://00red.com/blog/2016/07/27/tips-swift-xib-modular-design/swift

1、解決問題

Xib/Storybarod能夠方便、可視化的設置約束,在開發中也愈來愈重要。因爲Xib不能組件化,使得封裝、重用都變得不可行。本文將介紹一種解決方案,來實現Xib組件化。數組

2、模型塊原理

在介紹原理以前,咱們先弄清楚兩個概念:ide

從上圖能夠看出,分別選中File’s Owner及根視圖View,都有Custom Class屬性面板。其中Class屬性,有什麼做用,區別又是什麼呢?模塊化

2.1 View的Class屬性

View的Class屬性用於指定選中的視圖的實例化類。Xib其實是一個XML文件,在加載時,解析邏輯會根據XML內容,建立並設置View實例。而此處的Class就是告訴解析邏輯,想要建立什麼類的實例。若是此處設置爲UIButton,則解析邏輯會生成一個UIButton的實例。工具

2.2 File’s Owner的Class屬性

Feile’s Owner的Class屬性,大部分狀況下,都爲UIViewController及其子類。組件化

1
2

public func loadNibNamed(name: String!, owner: AnyObject!, options: [NSObject : AnyObject]!) -> [AnyObject]!

從上面xib的加載接口能夠看出,加載Xib須要指定一個owner類的實例,解析邏輯並無像2.1建立新實例,而是使用參數名爲owner的已建立好的實例。post

若是沒有建立,爲何還要指定File's Owner的Class屬性?

此處設置的Class屬性值,主要做用是經過關鍵字@IBOutlet,聲明有哪些屬性及方法能夠創建關聯關係。解析邏輯會將關聯視圖的引用賦值給owner的對應屬性,觸發事件則執行owner.method()方法。目的爲了在owner中,就能夠方便的處理界面相關的業務邏輯。能夠這樣理解,File’s Owner的Class,是關聯接口聲明,loadNibNamed傳入的owner是實現。ui

Tips

File’s Owner的Class屬性,起一個聲明做用,告知哪些屬性及方法可使用。spa

1
2
3
4
5
6
7
8
9
10
11
12
class ILViewController: UIViewController {

@IBOutlet weak var label: UILabel!

}


class ILFlagController: UIViewController {

@IBOutlet weak var label: UILabel!

}

既然如此(如上面代碼),使用loadNibNamed方法加載Xib時,owner參數傳入ILViewController實例,而Xib中File’s Owner的Class卻設置爲ILFlagController,是否可行?答案:可行。設計

2.4 Xib模塊化原理

在Storybarod/Xib中,與組件化有關的只有視圖的Class屬性。視圖是由xib解析邏輯建立,因此要實現組件化,就要在此Class實例化時,自動執行加載子xib模塊的功能。

3、工具類源碼

爲了實現xib的模塊化,須要有一個小的功能類:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
import UIKit

@objc class ILXibView: UIView {

@IBOutlet var contentView: UIView!


override init(frame: CGRect) {
super.init(frame: frame)
self.loadView()
}

required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}



override func awakeFromNib() {
super.awakeFromNib()
self.loadView()

}

override func layoutSubviews() {
super.layoutSubviews()
self.contentView.frame = self.bounds
}

private func getXibName() -> String {
let clzzName = NSStringFromClass(self.classForCoder)
let nameArray = clzzName.componentsSeparatedByString(".")
var xibName = nameArray[0]
if nameArray.count == 2 {
xibName = nameArray[1]
}
return xibName
}


func loadView() {
if self.contentView != nil {
return
}
self.contentView = self.loadViewWithNibName(self.getXibName(), owner: self)
self.contentView.frame = self.bounds
self.contentView.backgroundColor = UIColor.clearColor()
self.addSubview(self.contentView)
}

private func loadViewWithNibName(fileName: String, owner: AnyObject) -> UIView {
let nibs = NSBundle.mainBundle().loadNibNamed(fileName, owner: owner, options: nil)
return nibs[0] as! UIView
}



}

4、實戰示例

4.1 封裝Xib組件

新建ILDemoView.xibILDemoView.swift兩個文件(文件名要相同),並將ILDemoView文件的File’s Owner的Class設置爲ILDemoView

1
2
3
4
5
6
7
8
9
10
11
class ILDemoView: ILXibView {

@IBOutlet weak var label: UILabel!

override func awakeFromNib() {
//必定要調用super
super.awakeFromNib()
self.label.text = "你好,中國"
}

}

在xib文件中添加UILabel,並關聯到ILDemoView中

4.2 使用Xib組件

新建Xib/Storyboard文件,添加一個UIView控件,並將此控件的Class屬性設置爲ILDemoView

Tips

使用的時候,先設置目標UIView的Class屬性爲ILDemoView,再將此UIView控件拖拽創建關聯關係,會發現此時代碼中屬性類型已自動設置爲ILDemoViewILXibView簡單卻很是實用,咱們項目中已經大量的使用它,對於Xib的模塊化封裝,絕對是一利器。

 

 

之前使用xib時一直都有點疑問,xib中能夠有多個視圖控件,可是從xib中load出來的是一個數組,那麼怎麼肯定哪一個對象對應的是哪一個控件呢?

能夠實踐一下:

PurpleView.xib

purpleview_xib.png

隨便在xib文件中加了幾個視圖。

接下來將其load出來看看:

MainViewController.m

1
2
3
4
5
6
7
8
9
- (void)logViewsFromXIB {
     NSLog(@ "%s begin" , __func__);
     NSArray *views = [[NSBundle mainBundle] loadNibNamed:@ "PurpleView"  owner:nil options:nil];
     for  (int i = 0; i < views.count; i++) {
         id obj = views[i];
         NSLog(@ "%d : %@" , i, [obj class]);
     }
     NSLog(@ "%s end" , __func__);
}

控制檯輸出以下:

1
2
3
4
5
6
2015-01-09 15:03:06.629 JLN-1_xib[3139:121677] -[MainViewController logViewsFromXIB] begin
2015-01-09 15:03:06.635 JLN-1_xib[3139:121677] 0 : UIView
2015-01-09 15:03:06.635 JLN-1_xib[3139:121677] 1 : UIButton
2015-01-09 15:03:06.636 JLN-1_xib[3139:121677] 2 : UITableView
2015-01-09 15:03:06.636 JLN-1_xib[3139:121677] 3 : UILabel
2015-01-09 15:03:06.636 JLN-1_xib[3139:121677] -[MainViewController logViewsFromXIB] end

結論:

從xib中load出來的views數組中視圖對象的排列順序和xib scene中的對象排列順序一致(其實就是xml文件中元素的排序而已)。以下:

purpleview_xib_scene.png

能夠將其打亂並從新運行程序查看結果。

 

直接下載demo

2016.8.2更新

感謝 霰雪 檢查出ILXibView在6S不居中對齊問題,文章已經更新,感謝你們的支持。

 
 
版權聲明:一葉原創,採用  署名-非商業性使用-相同方式共享 3.0 中國大陸 許可協議
相關文章
相關標籤/搜索