解读IBInspectable和IB_DESIGNABLE

前言

很久之前在用YYLabel时,看到头文件里有IBInspectable这个关键字,由于我的开发习惯是用xib做比较多的,当时无意发现,把一个xib控件UIView指定为YYLabel类型时,Xcode面板attributes inspector栏里竟然多了一些YYLabel里面的属性,当时一看觉得很神奇,原来Xcode还可以自定义xib面板里的attributes inspector栏,当时设置了几个属性,运行时也生效了,但是第二天再次打开Xcode时,编译发现出现一个error,但是编译的最重结果success的,虽然不影响使用,但是一直有个红色的error很不爽,于是就用的方式进行创建和设置属性了。

最近在项目中,由于设计师的需求是按钮有个半透明的状态的按钮,类似于UIButton不可点击状态,但是这个按钮是可以响应事件的,用于提示此输入内容错处。所以要考虑在项目中使用自定义的UIButton的子类按钮满足这个需求。为了兼容xib和纯代码两种方式的使用和修改。想到之前看到过的IBInspectable

关于IBInspectable

Live RenderingYou can use two different attributes—@IBDesignable and @IBInspectable—to enable live, interactive custom view design in Interface Builder. When you create a custom view that inherits from the UIView class or the NSView class, you can add the @IBDesignable attribute just before the class declaration. After you add the custom view to Interface Builder (by setting the custom class of the view in the inspector pane), Interface Builder renders your view in the canvas.You can also add the @IBInspectable attribute to properties with types compatible with user defined runtime attributes. After you add your custom view to Interface Builder, you can edit these properties in the inspector.

大意上是根据runtime定义属性,而且是可审查、可看的意思。有点类似于自定义xib中的attributes inspector。可以实现在xib面板中使用自定义属性并可视化的修改。

但是支持的属性不多,包含以下几种


解读IBInspectable和IB_DESIGNABLE_第1张图片
inspector-enable-type

在设计自定义Button时,我考虑使用UIButton工厂的方式创建自定义Button,同时传入一个参数,就可以修改这个Button成为预先定义好的属性样式。只可惜IBInspectable不支持枚举属性,为了使IBInspectable支持,只能退而使用NSInteger属性来定义枚举参数。头文件代码如下:

#import 

/**
 根据项目UI需求,设置通用按组件在不同状态下的样式
 */
typedef NS_ENUM(NSUInteger, IBInspectable HHCustomStyleState){
    HHCustomStyleStateDefault        = 0,    ///< 正常状态
    HHCustomStyleStateDisabled       = 4,    ///< 不可用状态
    HHCustomStyleStateCustom1        = 100   ///< 自定义状态(允许交互的半禁用状态)
};

@interface HHCustomStyleButton : UIButton

/**
 设置自定义按钮状态
 设置参数值对应上面的枚举
 默认值 HHCustomStyleStateDefault
 */
@property (nonatomic, assign) IBInspectable NSInteger cutomStyleState;

+ (instancetype)buttonWithCutomStyleState:(HHCustomStyleState)cutomStyleState;


/**
 提供修改背景接口
 */
@property (nonatomic, strong) UIColor *defaultStateBgColor;
@property (nonatomic, strong) UIColor *disabledStateBgColor;
@property (nonatomic, strong) UIColor *custom1StateBgColor;
@end

此时的xib面板里面


解读IBInspectable和IB_DESIGNABLE_第2张图片
xib面板

不方便的地方时不能像UIButton通过枚举设置State Config,只能用NSInteger来替代枚举。

IBInspectable的使用

上面使用一个枚举样式的NSInteger来表述不同状态,一般情况下是满足项目中的使用了,但是有时候难免UI又会设计一些比较不同的样式,这时就要考虑Button组件扩展性了。

目前的设计是同时支持代码和xib使用,非特殊样式不用做自定义设置,但是加入要做自定义呢。做自定义可以分两种使用场景,一、纯代码创建使用,二、xib中创建使用。

  1. 纯代码中使用,以这样的方式使用
HHCustomStyleButton *btn = [HHCustomStyleButton buttonWithCutomStyleState:HHCustomStyleStateDefault];

以最接近UIButton的操作方式,这样修改或者替换或者使用都比较容易快速上手

  1. xib中的话,直接拖一个UIButton,指定它的类型为自定义的子类类型,本例中是HHCustomStyleButton,同时设置类型cutomStyleState

补充在xib中使用IBInspectable的其它信息:
一般情况下,以及大多数使用IBInspectable的地方,都是是要设置这个类为IB_DESIGNABLE,比如参考YYTextView

IB_DESIGNABLE
@interface YYTextView : UIScrollView 
@property (null_resettable, nonatomic, copy) IBInspectable NSString *text;
@property (nullable, nonatomic, strong) IBInspectable UIColor *textColor;
@property (nullable, nonatomic, strong) IBInspectable NSString *fontName_;

我最初也是这样设置,但是最后放弃使用IB_DESIGNABLE关键字
原因:

  1. 开发时,xib响应卡顿。因为是利用Runtime方式设置属性的,所以每次改动会实时反馈到界面上,但是Xcode这个地方做的不好,所以会卡顿

  2. Xcode自身的IBInspectable有Bug,像文章开头说道的会在编译时报错,同时xib的View变的不可见。

所以我这里没用IB_DESIGNABLE这个关键字,同时避免使用过多的IBInspectable入口来修改Xib界面,就是为了避免Xcode自身的Bug。需要自定义时,把这个控件IBOutlet出来,利用代码修改。

IBInspectable的不足之处

  1. 在Xcode中,使用OC的方式,IBInspectable是有Failed to update的Bug的,而且这个Bug是无解的,貌似有人说在Swift语言下似乎好一点,本人没有亲自尝试这个事情

  2. 每次自定义的Inspectable组件,它的Inspectable属性对应的runtime设置在User Defined Runtime Atttributes中不会自动清理。

总结

  1. IBInspectable一定程度上提供了自定义xib内部满足不了的设置,但是设置内容有限,使用不够方便。

  2. Xcode中的IBInspectable是有Bug的,这个是最严重的问题

  3. 基于自身Bug考虑,以及User Defined Runtime Atttributes中不会自动清理的问题,项目中不太建议大量使用IBInspectable,起码目前不建议

  4. 通过使用子类或者分类扩展的方式,IBInspectable可以方便的在xib中直接设置圆角,比之前使用User Defined Runtime Atttributes有多了一种更好的体验

下载Demo体验一下

你可能感兴趣的:(解读IBInspectable和IB_DESIGNABLE)