1. 程式人生 > >Swift 4 Xib 關聯 File's Owner 和 View 的區別

Swift 4 Xib 關聯 File's Owner 和 View 的區別

Xib 和 Storyboard 中, 右側控制面板中都有一個 Custom Class 屬性如下圖:

Xib: 

圖1

Storyboard : 

圖 2

Custom Class 中的 Class 選項用來自定義檢視或控制器的型別

 

本文重點介紹 xib 中, 設定 File's owner  的 Custom Class 和 設定 View 的 Custom Class 的區別

關聯 File's owner

File's Owner 是一個 Object 控制元件, 即 storyboard 中那個立方體圖形:

圖3

上圖 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