IB_DESIGNABLE 和 IBInspectable

Xcode 6开始,我们可以通过IB_DESIGNABLEIBInspectable属性实现自定义视图的实时渲染,即在代码中添加该功能后,可以在Interface Builder中直接查看和修改自定义视图,而非运行程序才能查看视图效果。

IBDesignable&IBInspectable.gif

这里我们讲述的是在Objective-C语言中,使用IB_DESIGNABLEIBInspectable,如果是在Swift中,应该使用@IBDesignable@IBInspectable替换。

1 IB_DESIGNABLE

IB_DESIGNABLE用于标记自定义视图的可设计性,在类定义时使用,可以轻松地调整自定义控件的呈现以得到想要的确切的结果。当应用到UIView的子类中时,IB_DESIGNABLE可以让Interface Builder知道它能在画布上直接渲染视图,任何改变,无论是从代码或属性检查器中,都将立即呈现在画布上。比如在CoreGraphics绘图过程中,在类名前使用IB_DESIGNABLE标记后,当我们更新drawRect:中的视图时,不必编译并运行应用程序,它会将更新结果立即显示在storyborad上。

IBDesignable&IBInspectable.png

注意,上图中的IB_DESIGNABLE添加在类的实现文件(.m文件)里,除此之外,还可以添加到类的头文件(.h文件)中,如下:

#import <UIKit/UIKit.h>

IB_DESIGNABLE

@interface testView : UIView

@end

2 IBInspectable

IBInspectable用于标记属性的可观察性。使用IBInspectable标记的属性会显示在storyboard中属性检查器的顶部,允许我们更改其内容,如果配合使用了IBDesignable,则会将更改结果实时显示在画布上。然而,IBInspectable并非对所有属性都适用,只有能够在 Runtime Attributes 中指定的类型才能够被标记后显示在IB中,目前IBInspectable只支持以下几种类型:

  • BOOL
  • NSNumber
  • NSString
  • NSRange
  • CGFloat
  • CGPoint
  • CGSize
  • CGRect
  • UIColor
  • UIImage

3 示例

下面我们通过一个简单的例子具体学习IB_DESIGNABLEIBInspectable的用法。

3.1 创建项目

首先打开Xcode,创建一个新的项目(File\New\Project...),选择iOS一栏下Application中的Single View Application模版,然后点击Next,填写项目选项。在Product Name中填写IBDesignableDemo,选择语言为Objective-C,点击Next,选择文件位置,并单击Create创建工程。

createProject.png

3.2 绘制自定义视图

绘制自定义视图一般需要创建一个UIView的子类,通过重写drawRect:方法并添加一些Core Graphics图形代码来实现。

在这里,我们首先创建一个新的文件(File\New\File...),选择iOS\Source\Cocoa Touch Class并命名新的CustomView类,使它成为UIView的子类,并确保语言为Objective-C,单击Next,然后单击Create创建。

createView.png

打开Main.storyboard,选中控制器中的View,在最右边的Identity Inspector中找到Custom Class一栏,将该类更改为刚才创建的CustomView类,这样我们就将控制器中的主视图改成了我们自定义的视图。

changeClass.png

打开CustomView.m文件,取消注释,在drawRect:方法中使用UIBezierPath绘制两个同心圆,代码如下:

- (void)drawRect:(CGRect)rect
{
    // 绘制最里面的圆
    UIBezierPath *innerPath = [UIBezierPath bezierPathWithArcCenter:self.center radius:60 startAngle:0 endAngle:2 * M_PI clockwise:YES];
    [innerPath setLineWidth:20];
    [[UIColor greenColor] setStroke];
    [innerPath stroke];
    
    // 绘制最外面的圆
    UIBezierPath *outterPath = [UIBezierPath bezierPathWithArcCenter:self.center radius:120 startAngle:0 endAngle:2 * M_PI clockwise:YES];
    [outterPath setLineWidth:20];
    [[UIColor redColor] setStroke];
    [outterPath stroke];
}

运行程序,我们会看到下图中的绘制结果:

drawCircles.png

关于使用UIBezierPath绘图的内容,可以参考文档相关文章

3.3 使用IB_DESIGNABLE查看绘制结果

如果不想运行模拟器,我们可以通过添加IB_DESIGNABLE,在storyboard中可以看到同样的绘制结果,更好的是,当我们修改代码,storyboard中的内容也会同步更新。

让我们先点击右上角的辅助编辑器,让storyboard显示在代码右侧,具体操作如下图:

showStoryboard.gif

也可以在顶部选择�View\Assistant Editor\Show Assistant Editor打开辅助编辑器。

现在我们看到的storyboard还是空白的,接下来我们在实现部分前面添加IB_DESIGNABLE关键词,再看storyboard,是的,代码中绘制的同心圆已经显示出来了:

addIBDesignable.png

尝试将代码中的绘制颜色设置为其它颜色看看!

3.4 使用IBInspectable自定义storyboard中的属性

为了便于设置颜色,我们声明两个UIColor的属性,并用IBInspectable标记,在@implementation CustomView前添加如下代码:

#import "CustomView.h"

IB_DESIGNABLE

// 新添加的代码
@interface CustomView ()

@property (nonatomic) IBInspectable UIColor *innerColor;
@property (nonatomic) IBInspectable UIColor *outterColor;

@end

@implementation CustomView

然后将两个圆的绘制颜色分别设置为该属性,修改drawRect:方法中代码如下:

- (void)drawRect:(CGRect)rect
{
    // 绘制最里面的圆
    ...
    [self.innerColor setStroke];
    [innerPath stroke];
    
    // 绘制最外面的圆
    ...
    [self.outterColor setStroke];
    [outterPath stroke];
}

然后打开属性检查器,我们会看到刚才声明的属性,将属性的内容修改为其他颜色,看看storyboard的变化:

colorProperty.png

接下来,我们继续添加一些属性来设置圆的半径和宽度:

@interface CustomView ()

@property (nonatomic) IBInspectable UIColor *innerColor;
@property (nonatomic) IBInspectable UIColor *outterColor;

// 新添加的属性
@property (nonatomic) IBInspectable CGFloat innerRadius;
@property (nonatomic) IBInspectable CGFloat outterRadius;

@property (nonatomic) IBInspectable CGFloat innerWidth;
@property (nonatomic) IBInspectable CGFloat outterWidth;

@end

然后修改drawRect:方法,将圆的半径和绘制的线宽设置为上面的属性:

- (void)drawRect:(CGRect)rect
{
    // 绘制最里面的圆
    UIBezierPath *innerPath = [UIBezierPath bezierPathWithArcCenter:self.center radius:self.innerRadius startAngle:0 endAngle:2 * M_PI clockwise:YES];
    [innerPath setLineWidth:self.innerWidth];
    [self.innerColor setStroke];
    [innerPath stroke];
    
    // 绘制最外面的圆
    UIBezierPath *outterPath = [UIBezierPath bezierPathWithArcCenter:self.center radius:self.outterRadius startAngle:0 endAngle:2 * M_PI clockwise:YES];
    [outterPath setLineWidth:self.outterWidth];
    [self.outterColor setStroke];
    [outterPath stroke];
}

打开属性检查器,修改属性内容,就可以自由地定义圆的颜色、大小和宽度:

IBDesignableDemo.gif

至此,我们已经学会了IB_DESIGNABLEIBInspectable的用法,在绘图中使用该功能替代运行模拟器,可以节省了大量的时间。然而它也有局限性,一般我们用它来绘制简单的代码,对于创建复杂的设计,storyboard常常会超时,这种情况下Playground可能是更好的选择。

最后,如果在创建demo中遇到问题,可以下载IBDesignableDemo查看完整代码。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,743评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,296评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,285评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,485评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,581评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,821评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,960评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,719评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,186评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,516评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,650评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,329评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,936评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,757评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,991评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,370评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,527评论 2 349

推荐阅读更多精彩内容