谈不完美的IBDesignable/IBInspectable可视化效果编程

我们好像慢慢地习惯了“理想很丰满,现实很骨感”这样顺序这样的转折这样常态,那么如果是“现实很丰满,理想很骨感”,我们能接受吗?现实丰满可以,但是理想很骨感那就不要将就了。就像薛之谦希望是能通过“丑八怪 呀啊呀啊呀哎呀”来唱红的自己,而不是上综艺做直男直到没朋友的谐星来笑红自己却跟他的歌关系不大。

苹果开发中使用的XCode也有这样的“现实丰满,理想骨感”例子,苹果公司在2011年就推出了UIStoryboard技术,到现在已经6年了。苹果还不在xcode的Interface Builder上直接提供修改控件的圆角,边框设置,而是提供IBDesignable/IBInspectable这样的技术让这些重复简单的工作由开发者来实现圆角外框,最后category上使用IBDesignable/IBInspectable却不能直接现实想要的结果。

那边我们来体验一下薛之谦的“人红歌不红”的“现实很丰满,理想很骨感”感觉。


文章思维导图.png

一.我们想要很简单

在Storyboard中的所有控件能通过Interface builder直接设置最基本圆角,边框和边框颜色属性,表达理想的Storyboard能显示出我要的渲染效果,而不是编写代码后只能在运行在手机或模拟器时才出现我们想要的效果。就像薛之谦想通唱歌红了自己,简单明了。

二.基本概念

  1. IB_DESIGNABLE的宏的功能就是让XCode动态渲染出该类图形化界面。UIView 或 NSView使用IB_DESIGNABLE宏声明时候,就是让Interface Builder知道它应该在UIStoryboard或者Xib中画布上直接渲染视图,不需要等到编译运行后就能预先展示出来效果 。
  1. IBInspectable修饰属性,可以是用户自定义的运行时属性,让支持KVC的属性能够在Attribute Inspector中配置。

三.使用方式

1.IB_DESIGNABLE放在@interface或者@implement都可以,申明这个类在XCode直接看到渲染的效果。
IB_DESIGNABLE
@interface IBDesignableImageView : UIImageView
2.IBInspectable 修饰属性,使属性能在XCode中直接设置。**
@property(nonatomic,assign) IBInspectable CGFloat cornerRadius;

四 .普通类继承关系实现渲染效果

根据第三所列出的2个关键点,详细具体实现:

1.自定义IBDesignableImageView 继承UIImageView。
#import <UIKit/UIKit.h>
IB_DESIGNABLE
@interface IBDesignableImageView : UIImageView
    @property(nonatomic,assign) IBInspectable CGFloat cornerRadius;
@end
2.接着在IBDesignableImageView.m文件实现下set方法
#import "IBDesignableImageView.h"
@implementation IBDesignableImageView
-(void)setCornerRadius:(CGFloat)cornerRadius{
    _cornerRadius = cornerRadius;//不要使用self.cornerRadius = cornerRadius;这样会死循环
    self.layer.masksToBounds = YES;
    self.layer.cornerRadius = cornerRadius;
}
@end
3.接着,XCode中Customer Class选择IBDesignableImageView。
4.最后,interface builder属性栏中设置你刚刚属性。
类继承关系实现效果图

主要就是以上四步基本满足一下下storyboard成功展示一种View实时渲染效果的快感,犹如薛之谦尝试到一首《丑八怪》火一阵子,爽一阵子的快感,并且不会让人误认为这是赵全的《我很丑可是我很温柔》的续本。

五.UIView的Category实现渲染效果

尝到了好处,自然想到实现通用的方式给需要控件都加上interface builder可设置相关属性。所以,我们自认为UIView其他子View父类,那么如果UIView可是直接在XCode上设置属性实现渲染,那么其他子View随之得到渲染效果。

1.我们最想看到的结果是

我们最想看到结果是,UIImageView、UITextField、UIButton等等都能如愿的被interface builder直接修改相关圆角,边框等等属性。噔噔,我们脑海浮现以下画面:


最理想状态
2.编写UIView的Category类UIView+MGO.h
#import <UIKit/UIKit.h>
IB_DESIGNABLE
@interface UIView (MGO)
    @property(nonatomic,assign) IBInspectable CGFloat cornerRadius;
    @property(nonatomic,assign) IBInspectable CGFloat borderWidth;
    @property(nonatomic,assign) IBInspectable UIColor *borderColor;
    @property(nonatomic,assign) IBInspectable CGFloat defineValue;
@end
3.编写UIView+MGO.m中的实现
#import "UIView+MGO.h"
#import <objc/runtime.h>
@implementation UIView (MGO)
-(void)setCornerRadius:(CGFloat)cornerRadius{
    self.layer.masksToBounds = YES;
    self.layer.cornerRadius = cornerRadius;
}
-(void)setBorderColor:(UIColor *)borderColor{
    self.layer.borderColor = borderColor.CGColor;
}
-(void)setBorderWidth:(CGFloat)borderWidth{
    self.layer.borderWidth = borderWidth;
}
-(void)setDefineValue:(CGFloat)defineValue{
    objc_setAssociatedObject(self, @selector(defineValue), @(defineValue),OBJC_ASSOCIATION_ASSIGN);
}
-(CGFloat)cornerRadius{
    return self.layer.cornerRadius;
}
-(CGFloat)borderWidth{
    return self.layer.borderWidth;
}
-(UIColor *)borderColor{
    return [UIColor colorWithCGColor:self.layer.borderColor];
}
-(CGFloat)defineValue{
    return [objc_getAssociatedObject(self, @selector(defineValue)) floatValue];
}
@end

这个.m的实现类,有几个知识点要注意:
1).category中添加IBInspectable修饰属性,必须带有set和get的方法,不然编译都通过。
2).KVC观察属性值变化,从而得到即时刷新效果。
3).category中自定义属性如上边defineValue属性,使用runtime方式赋值。所以会有objc_setAssociatedObject(self, @selector(defineValue), @(defineValue),OBJC_ASSOCIATION_ASSIGN);这样的代码。_defineValue = defineValue;这样也是行,这样是有语法问题的。
详细的runtime和KVC知识点可以查看《谈Runtime机制和使用的整体化梳理》《谈KVC、KVO(重点观察者模式)机制编程》

4.在interface builder设置相关属性

1).属性栏可以看可设置圆角,边框宽度等


设置UIView(MGO定义出来属性)

2).Runtime Attribute栏中也能自动生成刚刚设置的属性值


Runtime Attribute显示属性值
5.查看storyboard上的头像有没有显示设置的属性值
UIView(MGO)展示的效果

Oh。。。my god!storyboard上一点效果也没显示出来,反而模拟器运行效果确实理想的状态。活生生的“现实很丰满,理想很骨感”表现得淋漓尽致。难道要硬着头皮瞬间退回到解放前,重复不断的写继承代码。。。打死也不,,,告诉你淘宝发过来的验证码!

六.曲线救国处理Category不显示效果问题

曲线救国生活中可以,国就是救那么一两次,没国了也没办法。程序中,每时每刻都在救国,明摆着这欺负人嘛!不过,国我们还是得救的,歌薛之谦还是要唱的,先找到两者的微妙关系,串成曲线才行。于是乎,薛之谦将段子手的头衔发挥到极致,参加各大综艺,《火星情报站》《极限挑战》《大学生来了》等等,趁机唱唱“丑八怪 呀啊呀啊哎呀”,道理就明了了,就是死活出现在人面前晃来晃去。
哟,那会不会interface builder死活要看到UIView的自定义子类的继承类,设置在Customer Class中才行啊。试试?

1.编写一个 空白MGOImageView继承UIImageView。
#import <UIKit/UIKit.h>
@interface MGOImageView : UIImageView
@end
2.MGOImageView.m文件什么也不干,就是等机会对接UIView(MGO)自定义属性。
#import "MGOImageView.h"
@implementation MGOImageView
@end
3.选中storyboard中的UIImageView在Customer Class选择 MGOImageView。
编写空白MGOImageView尝试

噢,,,了个天啊!storyboard上一点效果都没有少显示出来,反而吓到了现实中的我。那就趁热吃豆腐了,把其他控件都写一个对应空白的子类,设置在customer class上。


其他控件都添加对应的子类

好像幸福就是来得那么突然,伤心的小船说翻就翻了。会不会有更大幸福,于是乎,小明在google上搜索“IBDesignable/IBInspectable在Category中没有效果”。看了两三页搜索结果,最后比较接近的是Cocachina中也有一个没有人回复的相关帖子,和另外一篇跟我的发现一样要写一个空白的子类设置在Customer Class 中才行。

七.对比总结

经过以上一系列折腾,最后的结果确认令我觉得“不完美的IBDesignable/IBInspectable”。有些对XCode,Storyboard项目者有些一丁点的期待外,同时也是希望有开发者提供更好的处理方式。对比其他IDE,,就算了。追求完美我们是天生的,尽情开发我们也是认真的。

八.源码下载

https://github.com/minggo620/iOSDesignable.git
好想要到薛之谦的微信,向他发1毛钱的红包,然后他会一如既往地回“不好意思,我不收别人的微信红包”,接着我收到了200块红包。

【原创出品 未经授权 禁止转载】
【欢迎微友分享转发 禁止公号等未经授权的转载】

微信公众号:minggo_dev

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

推荐阅读更多精彩内容