前言
在iOS開發(fā)中悲柱,使用storyboard的某些場景下我們可能希望同時使用xib定義一些可以重復利用的view钧敞,并在storyboard中調(diào)用锅必。本文將分享一種此類xib bridge的簡單實現(xiàn)方式伐脖。
實現(xiàn)思路
本方法的思路是將xib的File's Owner所對應的UIView作為placeholderView
介粘,其作用只是在storyboard中起到占位作用秉犹,并承載storyboard中與xib自定義view相關的AutoLayout約束蛉谜,其背景色將被設為[UIColor clearColor]
,并且不顯示任何內(nèi)容崇堵。顯示自定義內(nèi)容的任務將交給一個UIView
--contentView
型诚,它將作為placeholderView
的子視圖。
為了使在storyboard中作用于placeholderView
的AutoLayout約束能夠自動的作用于contentView
鸳劳,可以向placeholderView
添加NSLayoutRelationEqual
約束狰贯,讓placeholderView
和contentView
的上下左右四個NSLayoutAttribute
分別完全相等,這樣contentView
在storyboard中的的frame將完全和placeholderView相同,從而達到目的涵紊。
以上方法同樣可以適用于xib的某個子view是另外一個xib的情形傍妒。
實現(xiàn)方法
首先進行如下準備工作
- 創(chuàng)建一個xib,用于實現(xiàn)子view的自定義內(nèi)容摸柄,本文中命名為
CoverView.xib
颤练。 - 創(chuàng)建一個
UIView
的子類,作為placeholderView
的基類塘幅,用于進行xib bridge相關的添加約束和添加contentView
等工作昔案,本文中命名為XibBridgeBaseView
。 - 創(chuàng)建一個
XibBridgeBaseView
的子類电媳,用于存儲xib中自定義內(nèi)容的相關屬性并進行相關操作踏揣,本文中命名為CoverView
實現(xiàn)子view的xib文件
首先需要在identity inspector中將xib文件的File's Owner設置成為創(chuàng)建好的CoverView
類
接下來我們就可以在xib中自動創(chuàng)建的UIView
子視圖中進行自定義UI了,此時可以在CoverView
類中創(chuàng)建該UIView
子視圖(這里命名為contentView
)以及其他UI組件的IBAction
和IBOutlet
等匾乓。
實現(xiàn)占位視圖的基類
作為placeholderView
的基類捞稿,XibBridgeBaseView
中定義了如下的一個方法,用于從nib中載入contentView并添加進占位視圖的子視圖中拼缝,其中XibBridgeBaseView
的initWithCoder:
方法將使用其派生子類的類名作為xib的名字娱局,因此子類和其所對應的xib文件應該使用相同的命名。
@implementation XibBridgeBaseView
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
[self setupXibBridgeWithPlaceholderViewNibName:NSStringFromClass([self class])];
}
return self;
}
- (void)setupXibBridgeWithPlaceholderViewNibName:(NSString *)placeholderViewNibName {
UIView *contentView =[[[NSBundle mainBundle] loadNibNamed:placeholderViewNibName
owner:self
options:nil] objectAtIndex:0];
[self setBackgroundColor:[UIColor clearColor]];
[self addSubview:contentView];
[self setXibBridgeConstraintsToContentView:contentView];
}
其中- (void)setXibBridgeConstraintsToContentView:(UIView *)contentView
方法主要是實現(xiàn)前文提到的通過向占位視圖添加NSLayoutRelationEqual
約束讓placeholderView
和contentView
的上下左右四個NSLayoutAttribute
分別完全相等:
@implementation XibBridgeBaseView
- (void)setXibBridgeConstraintsToContentView:(UIView *)contentView {
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[contentView]|"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(contentView)]];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[contentView]|"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(contentView)]];
//為保證AutoLayout生效咧七,必須加上下面這句話
contentView.translatesAutoresizingMaskIntoConstraints = NO;
}
實現(xiàn)占位視圖的實際類
作為placeholderView
的實際類衰齐,每創(chuàng)建一個需要被橋接的xib時就要創(chuàng)建一個對應的實際類(本文中為CoverView
類),CoverView
中將包含在xib中定義的自定義UI相關的屬性和操作:
@interface CoverView : XibBridgeBaseView
@property (weak, nonatomic) IBOutlet UILabel *headerLabel;
@property (weak, nonatomic) IBOutlet UIButton *submitButton;
@property (strong, nonatomic) IBOutlet UIView *contentView;
@implementation CoverView
- (IBAction)submitButtonClicked:(UIButton *)sender {
NSLog(@"Hello World!");
}
因為我們是用父storyboard或者xib來調(diào)用placeholderView
的继阻,實際使用中只需要將placeholderView
的實際類繼承于基類xibBridgeBaseView
耻涛,即可實現(xiàn)橋接功能。該placeholderView
的其他初始化工作可以放在- awakeFromNib
中進行
@implementation CoverView
- (void)awakeFromNib {
self.contentView.backgroundColor = [UIColor clearColor];
[self.contentView.layer setBorderColor:[[UIColor whiteColor] CGColor]];
[self.contentView.layer setBorderWidth:1.0];
}
在父的storyboard或者xib中調(diào)用placeholderView
做完以上步奏后瘟檩,只需在父storyboard或者xib中拖一個UIView
來作為placeholderView
抹缕,并在identity inspector中將其class屬性設置成為對應的placeholderView
的實際類即可。
結(jié)語
在使用如上方法來進行xib橋接的過程中需要注意一下幾點使用方式:
- 在父的storyboard或者xib中墨辛,只需要對拖入的
placeholderView
添加AutoLayout約束即可 - 在子xib中各個UI組件只需要跟
contentView
建立AutoLayout約束即可 - 對于
placeholderView
的identity inspector相關參數(shù)需要在子xib中對File's Owner進行設置 - 對于
placeholderView
的attribute inspector相關參數(shù)需要在父storyboard或者xib中進行設置
對于xib橋接問題大神SUNNYXX給出了一個更高端的解決方案卓研,利用到了iOS runtime相關的技術。
本文個人博客地址: http://wty.im/2016/02/29/use-view-defined-by-xib-in-storyboard/
Github: https://github.com/wty21cn/