交互設(shè)計(jì)和UI設(shè)計(jì)水準(zhǔn)很大程度影響著用戶對(duì)應(yīng)用的評(píng)價(jià),iOS開(kāi)發(fā)發(fā)展至今已逾10年,開(kāi)發(fā)者對(duì)于界面UI編碼的習(xí)慣逐漸分化成三大流派:
- code - 易追蹤、可復(fù)用、便于版本控制,但不直觀
- xib - 簡(jiǎn)單便捷、直觀、一一對(duì)應(yīng),但易沖突
- storyboard - 邏輯清晰、簡(jiǎn)單易用、直觀高效,雖易沖突、復(fù)用性不佳,但仍是未來(lái)趨勢(shì)
xib 和 storyboard 均采用了 Interface Builder(IB)來(lái)生成GUI,通過(guò)面板上簡(jiǎn)單的拖拽替代繁瑣冗余的code來(lái)構(gòu)建頁(yè)面。但我們經(jīng)常發(fā)現(xiàn),既有的功能并不能完全滿足布局的需要,那么,我們可以通過(guò)在特定的位置定義可視化屬性IBInspectable、定義宏IB_DESIGNABLE來(lái)精簡(jiǎn)代碼。
下文具體介紹一下如何使用。
【場(chǎng)景】設(shè)置按鈕:圓角
cornerRadius:8pt、邊框顏色borderWidth:1pt、邊框?qū)挾?code>borderColor:系統(tǒng)藍(lán)色
巧用IBInspectable
【IBInspectable】 這一屬性提供了訪問(wèn)功能的新方式:用戶自定義的運(yùn)行時(shí)屬性,讓支持KVC的屬性能夠在身份檢查器(Identity Inspector)的 User Defined Runtime Attributes 中配置。
它支持修飾的屬性類型有:BOOL、NSNumber、CGPoint、CGSize、CGRect、UIColor、NSString、NSLocalizedString、NSRange、UIImage、NSNull。
如果想讓特定類型的控件設(shè)置某個(gè)屬性,可以為對(duì)應(yīng)的UIKit添加分類,為定義該屬性時(shí)加上IBInspectable,示例:
#import <UIKit/UIKit.h>
@interface UIButton (HTAdditions)
@property (nonatomic) IBInspectable CGFloat kCornerRadius;
@property (nonatomic) IBInspectable CGFloat kBorderWidth;
@property (nonatomic,copy) IBInspectable UIColor *gBorderColor;
@end
這時(shí)Xcode的Attributes Inspector欄中就會(huì)出現(xiàn)三個(gè)新的可編輯屬性。

Identity Inspector下的 User Defined Runtime Attributes也會(huì)出現(xiàn)相應(yīng)的key path和value值。

設(shè)置好后run一下工程就能看到場(chǎng)景中要求的效果,但通常開(kāi)發(fā)者不需要所有的按鈕都設(shè)置圓角、邊框,更多的是采用自定義視圖的形式統(tǒng)一處理相似風(fēng)格的control。為了更高效地開(kāi)發(fā),接下來(lái)介紹宏定義IB_DESIGNABLE。
巧用IB_DESIGNABLE
【IB_DESIGNABLE】 在類名前加上此宏定義,初始化、布置和繪制方法將被用來(lái)在畫(huà)布上渲染該類的自定義視圖。
操作步驟:
- storyboard中拖拽一個(gè)UIButton;
- 創(chuàng)建父類是UIButton的HTCustomButton類文件,并在.h的
interface前定義IB_DESIGNABLE; - 給步驟1按鈕的Custom Class關(guān)聯(lián)上HTCustomButton。
這時(shí)我們就可以直接在User Defined Runtime Attributes中加入想要的屬性,例如圓角、邊框?qū)挾鹊?。邊框顏色由于UIColor類型的特殊性,需要重新定義。
HTCustomButton.h:
#import <UIKit/UIKit.h>
IB_DESIGNABLE
@interface HTCustomButton : UIButton
/** 設(shè)置邊框顏色可視化 */
@property (nonatomic, strong)IBInspectable UIColor *customBorderColor;
@end
HTCustomButton.m:
#import "HTCustomButton.h"
@implementation HTCustomButton
/**
* 設(shè)置邊框顏色
*
* @param customBorderColor 可視化視圖傳入的值
*/
- (void)setCustomBorderColor:(UIColor *)customBorderColor {
self.layer.borderColor = customBorderColor.CGColor;
}
@end
設(shè)置好后就可以直接添加或修改相應(yīng)的屬性動(dòng)態(tài)刷新控件,如下圖:

純代碼開(kāi)發(fā)流派如何借助IB_DESIGNABLE動(dòng)態(tài)查看布局效果
對(duì)于很多被強(qiáng)制勒令用純代碼coding的開(kāi)發(fā)者來(lái)說(shuō),下面介紹的干貨絕對(duì)會(huì)大大提升開(kāi)發(fā)效率。
舉個(gè)例子:創(chuàng)建基于UIView的HTMasonryView,以及同名的.xib文件,并在Custom Class中關(guān)聯(lián)好。接下來(lái)在HTMasonryView.m中創(chuàng)建并布局masonryButton,注意添加IB_DESIGNABLE,代碼如下:
#import "HTMasonryView.h"
#import <Masonry.h>
#import "UIButton+HTAdditions.h"
IB_DESIGNABLE
@interface HTMasonryView ()
@property (nonatomic, strong) UIButton *masonryButton;
@end
@implementation HTMasonryView
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
[self setupView];
}
return self;
}
-(instancetype)initWithCoder:(NSCoder *)aDecoder {
if (self = [super initWithCoder:aDecoder]) {
[self setupView];
}
return self;
}
- (void)setupView {
_masonryButton = ({
UIButton *btn = [UIButton buttonWithType:UIButtonTypeSystem];
btn.kCornerRadius = 8.0f;
btn.kBorderWidth = 1.0f;
btn.gBorderColor = btn.ht_normalTitleColor;
btn.ht_normalTitle = @"code創(chuàng)建-Masonry布局的按鈕";
btn.titleLabel.font = [UIFont systemFontOfSize:14.0f];
[self addSubview:btn];
btn;
});
[self layout];
}
- (void)layout {
__weak __typeof(self) weakSelf = self;
[_masonryButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(30);
make.right.mas_equalTo(-30);
make.top.bottom.mas_equalTo(weakSelf);
}];
}
@end
點(diǎn)開(kāi)HTMasonryView.xib查看會(huì)發(fā)現(xiàn)已經(jīng)渲染出了Masonry的布局效果。

ps:如果渲染失敗,查看Editor->Automatically Refresh Views 是否勾選,嘗試重啟Xcode。
開(kāi)啟成功的特點(diǎn)就是Show the Identity inspector->Custom Class->Designables:Up to date(更新完畢)/Updating(更新中),如果顯示Build failed建議檢查布局代碼。
歡迎評(píng)論,最后-> Demo傳送門(mén)