首先直入正題:@IBInspectable & @IBDesignablehtml
對於 @IBInspectable 和 @IBDesignable 可詳見官方文檔 : Creating a Custom View That Renders in Interface Builderios
固然也能夠閱讀下中文版的: http://nshipster.cn/ibinspectable-ibdesignable/swift
若是自定view是本身用純代碼寫的,對於上面兩種處理都比較簡單,只須要指定類名便可。xcode
可是若是這個自定義view是用寫的,那麼若是讓xib的界面直接render到storyboard呢?app
1. 建立一個IDView,添加一個IDView.Xibiview
2. 對IDCard.xib添加約束ide
3. 在IDCard.xib的 File's Owner class 設置爲IDCard:ui
4. 在IDCard.swift中添加以下代碼,把xib的view連線到代碼上的contentView:spa
5. 綁定xib,實現 @IBInspectable, @IBDesignable這幾部分代碼3d
@IBDesignable class IDCard: UIView { @IBOutlet var contentView: UIView! @IBInspectable var cornerRadius: CGFloat = 0 { didSet { layer.cornerRadius = cornerRadius layer.masksToBounds = cornerRadius > 0 } } @IBInspectable var borderWidth: CGFloat = 0 { didSet { layer.borderWidth = borderWidth } } @IBInspectable var borderColor: UIColor? { didSet { layer.borderColor = borderColor?.CGColor } } override init(frame: CGRect) { super.init(frame: frame) initialFromXib() } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) initialFromXib() } func initialFromXib() { let bundle = NSBundle(forClass: self.dynamicType) let nib = UINib(nibName: "IDCard", bundle: bundle) contentView = nib.instantiateWithOwner(self, options: nil)[0] as! UIView contentView.frame = bounds addSubview(contentView) } }
6. 在Main.storyboard實現拖入view,並指定其class爲IDCard,並對其進行約束
7. 運行代碼,結果以下
總結遇到的一些坑:
1. 如何讓 sb上的約束生效
2. 如何讓xib渲染到sb上
上面的兩個問題都在initialFromXib上解決
func initialFromXib() { let bundle = NSBundle(forClass: self.dynamicType) let nib = UINib(nibName: "IDCard", bundle: bundle) contentView = nib.instantiateWithOwner(self, options: nil)[0] as! UIView contentView.frame = bounds // 問題1的解決方案 addSubview(contentView) }
那麼爲何要設置contentView.frame = bounds?
首先咱們都知道程序首先會加載vc對應的sb,那麼sb上相關的約束等會對其上的view進行渲染,那麼這個時候 IDCard.xib也會獲得渲染,若是咱們這個時候不設置contentView的frame的話,
那麼這個時候contentView的frame將會被xib上的覆蓋掉,那麼這個時候contentView的大小隻能是你在xib上的大小。這個時候也是凸顯爲何要有contentView這個屬性了。由於
self = nib.instantiateWithOwner(self, options: nil)[0] as! UIView
這是不被編譯經過的。
問題2, 在寫這個例子的時候,我加載這個
contentView = NSBundle.mainBundle().loadNibNamed("Xib", owner: self, options: nil)[0] as! UIView
替代
let bundle = NSBundle(forClass: self.dynamicType)
let nib = UINib(nibName: "IDCard", bundle: bundle)
contentView = nib.instantiateWithOwner(self, options: nil)[0] as! UIView
這個時候咱們看在sb上看不到IDCard這個view,或者報錯"Failed to update auto layout status"。緣由待查,可參考
還有一個可能的緣由:
NIb加載會把xib文件加載到內存中,讀取快,常常使用的xib文件可使用nib加載,
Bundle加載,每次會從磁盤上加載,效率會慢一點
3. 還有在其餘須要注意的點
在用@IBDesignable時候, 你最好重寫init(frame:) 和 init(coder:)這兩個初始化方法
在xib中,你不須要給這個view的class設置爲IDCard,默認的UIView就好
關聯文章: 文章