Swift 4 Xib 關聯 File's Owner 和 View 的區別
Xib 和 Storyboard 中, 右側控制面板中都有一個 Custom Class 屬性如下圖:
Xib:
Storyboard :
Custom Class 中的 Class 選項用來自定義檢視或控制器的型別
本文重點介紹 xib 中, 設定 File's owner 的 Custom Class 和 設定 View 的 Custom Class 的區別
關聯 File's owner
File's Owner 是一個 Object 控制元件, 即 storyboard 中那個立方體圖形:
上圖 Object 控制元件簡介: object 控制元件為 Interface Builder 中不能直接獲取的物件提供一個模板, 你可以將這個 object 例項化為你在 Custom Class 的 Class 中指定型別的例項變數.
也就是說給 xib 中 File's owner 的 Custom Class Class 設定一個型別, 則 File's owner 就是該型別的一個例項
關聯 File's owner 的 Custom Class
1.直接在 storyboard 中使用, 使用方法參考:
【iOS】Storyboard載入Xib自定義view(Swift)
2.程式碼中使用, 重寫 init 方法, 將 xib 中的 View 拉為約束 contentView 新增在 self :
方法一: 直接在自定義類中獲取 View
@IBOutlet var contentView: UIView!//xib 中的 View 拉為約束 contentView @IBOutlet weak var label: UILabel! //程式碼建立, 執行此方法, 不執行 init?(coder aDecoder: NSCoder) override init(frame: CGRect) { super.init(frame: frame) awakeFromNib() } //新增在 storyboard 上, 執行此方法 required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) } override func awakeFromNib() { super.awakeFromNib() setupContentView() } func setupContentView() { //owner 一定要為 self, 不能為 nil let contentView = Bundle.main.loadNibNamed("CustomView_Fileowner", owner: self, options: nil)?.first as! UIView contentView.frame = self.bounds contentView.autoresizingMask = [.flexibleWidth, .flexibleHeight] addSubview(contentView) }
方法二: 使用 Swift 的協議, 在協議擴充套件中獲取 View 並新增
protocol NibLoadableProtocol { }
extension NibLoadableProtocol where Self : UIView {
//設定 File's Owner 的 CustomClass
//例項方法
func loadNibFileOwner(_ nibNmae: String? = nil) -> UIView {
//獲取例項的型別
let object: AnyObject = object_getClass(self)!
//"\(object)": AntennaParameters.XXXXXX
//獲取真正的型別名
let className = type(of: object).description().components(separatedBy: ".").last
let contentView = Bundle.main.loadNibNamed(nibNmae ?? className!, owner: self, options: nil)?.first as! UIView
contentView.frame = self.bounds
contentView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
addSubview(contentView)
return contentView
}
}
//讓 CustomView_Fileowner 服從協議
extension CustomView_Fileowner: NibLoadableProtocol { }
@IBOutlet var contentView: UIView!
@IBOutlet weak var label: UILabel!
//程式碼建立, 執行此方法, 不執行 init?(coder aDecoder: NSCoder)
override init(frame: CGRect) {
super.init(frame: frame)
awakeFromNib()
}
//新增在 storyboard 上, 執行此方法
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func awakeFromNib() {
super.awakeFromNib()
//協議方法
contentView = loadNibFileOwner()
}
關聯 View 的 Custom Class
1.使用類方法
//View 中, 類方法
class func newInstance() -> CustomView_View {
//owner 為 nil
return Bundle.main.loadNibNamed("CustomView_View", owner: nil, options: nil)?.first as! CustomView_View
}
// Controller 中
//使用型別方法建立
let viewView = CustomView_View.newInstance()
viewView.frame = CGRect(x: 50, y: 400, width: 200, height: 100)
view.addSubview(viewView)
2.使用協議擴充套件
protocol NibLoadableProtocol { }
extension NibLoadableProtocol where Self : UIView {
/*
static func loadNib(_ nibNmae :String = "") -> Self{
let nib = nibNmae == "" ? "\(self)" : nibNmae
return Bundle.main.loadNibNamed(nib, owner: nil, options: nil)?.first as! Self
}
*/
//型別方法
static func loadNib(_ nibNmae: String? = nil) -> Self {
return Bundle.main.loadNibNamed(nibNmae ?? "\(self)", owner: nil, options: nil)?.first as! Self
}
}
extension CustomView_View: NibLoadableProtocol { }
//使用協議擴充套件建立, 型別方法
let viewView = CustomView_View.loadNib()
viewView.frame = CGRect(x: 50, y: 510, width: 200, height: 100)
view.addSubview(viewView)
總結:
關聯 File's Owner :
則 self 是 Custom Class自定義型別的一個例項, 要將 View 拉為約束新增在 self, 可以直接新增在 storyboard 上使用, 在程式碼中使用時, 要使用物件方法, Bundle.main.loadNibNamed 方法中 owner 為 self
關聯 View :
則 self 是 Custom Class自定義型別, 型別不能直接新增在 storyboard, 程式碼中, 程式碼中使用時, 要使用型別方法, Bundle.main.loadNibNamed 方法中 owner 為 nil