iOS 给分类category添加属性

一、问题:给分类(category)添加属性

  1. 最近遇到一个问题:需要在一个类的Category中添加属性;
  2. 可以通过 Category 给一个现有的类添加属性,但是却不能添加实例变量;
  3. 解决方案:通过runtime建立关联引用;

二、解决:runtime建立关联引用

1.引入runtime头文件

#import <objc/runtime.h>

2.添加属性

可以在分类(即.m文件)中添加,也可以在分类的头文件(即.h文件)中添加。

@interface UIView (EmptyView)

@property (nonatomic, strong) UIButton *hideButton;

@end

3.实现getter、setter

1).在implementation中添加属性的getter和setter方法。

//getter 
- (UIButton *)hideButton {
    UIButton *_hideButton = objc_getAssociatedObject(self, @selector(hideButton));
    if (!_hideButton) {
        _hideButton = [UIButton buttonWithType:UIButtonTypeCustom];
        _hideButton.frame = CGRectMake(self.bounds.size.width/2-110, 260, 220, 44);
        _hideButton.backgroundColor = [UIColor brownColor];
        [_hideButton setTitle:@"Hide" forState:UIControlStateNormal];
        objc_setAssociatedObject(self, @selector(hideButton), _hideButton, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    return _hideButton;
}

//setter
- (void)setHideButton:(UIButton *)hideButton {
    objc_setAssociatedObject(self, @selector(hideButton), hideButton, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

2).在hideButton中使用的objc_getAssociatedOject方法,Object-C中描述如下:

/** 
 * Returns the value associated with a given object for a given key.
 * 
 * @param object The source object for the association.
 * @param key The key for the association.
 * 
 * @return The value associated with the key \e key for \e object.
 * 
 * @see objc_setAssociatedObject
 */
OBJC_EXPORT id objc_getAssociatedObject(id object, const void *key)
    OBJC_AVAILABLE(10.6, 3.1, 9.0, 1.0);

  • <a href = http://blog.leichunfeng.com/blog/2015/06/26/objective-c-associated-objects-implementation-principle/>这个函数先根据对象地址在 AssociationsHashMap 中查找其对应的 ObjectAssociationMap 对象,如果能找到则进一步根据 key 在 ObjectAssociationMap 对象中查找这个 key 所对应的关联结构 ObjcAssociation ,如果能找到则返回 ObjcAssociation 对象的 value 值,否则返回 nil ;</a>
  • 也就是在和self建立了关联引用的所有对象中通过key找到某一个特定的对象,如果有返回该对象的value,否则,返回 nil 。
  • objc_getAssociatedObject有两个参数,第一个参数为从该object中获取关联对象,第二个参数为想要获取关联对象的key;

对于第二个参数const void *key,有以下四种推荐的key值:

  • 声明 static char kAssociatedObjectKey; ,使用 &kAssociatedObjectKey 作为 key 值;
  • 声明 static void *kAssociatedObjectKey = &kAssociatedObjectKey;,使用 kAssociatedObjectKey 作为key值;
  • selector ,使用 getter 方法的名称作为key值;
  • 而使用_cmd可以直接使用该@selector的名称,即hideButton,并且能保证改名称不重复。(与上一种方法相同)

3).在setHideButton中使用的objc_setAssociatedObject方法,Object-C中描述如下:

/** 
 * Sets an associated value for a given object using a given key and association policy.
 * 
 * @param object The source object for the association.
 * @param key The key for the association.
 * @param value The value to associate with the key key for object. Pass nil to clear an existing association.
 * @param policy The policy for the association. For possible values, see “Associative Object Behaviors.”
 * 
 * @see objc_setAssociatedObject
 * @see objc_removeAssociatedObjects
 */
OBJC_EXPORT void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
    OBJC_AVAILABLE(10.6, 3.1, 9.0, 1.0);

参数说明:

  • objectkey同于objc_getAssociatedObject;
  • value:需要和object建立关联引用对象的value;
  • policy:关联策略,等同于给property添加关键字,具体说明如下表关联策略

关联策略

|关联策略 |等价属性|说明|
|------|------|------|------|
|OBJC_ASSOCIATION_ASSIGN| @property (assign) or @property (unsafe_unretained)| 弱引用关联对象|
|OBJC_ASSOCIATION_RETAIN_NONATOMIC| @property (strong, nonatomic)| 强引用关联对象,且为非原子操作|
|OBJC_ASSOCIATION_COPY_NONATOMIC| @property (copy, nonatomic)| 复制关联对象,且为非原子操作|
|OBJC_ASSOCIATION_RETAIN| @property (strong, atomic)| 强引用关联对象,且为原子操作
|OBJC_ASSOCIATION_COPY| @property (copy, atomic)| 复制关联对象,且为原子操作|

4.对添加的属性操作

例如将添加的hideButton属性添加到View中

- (void)showHideButton {
    if (!self.hideButton.superview) {
        [self addSubview:self.hideButton];
    }
}

参考资料

  1. <a href = http://blog.leichunfeng.com/blog/2015/06/26/objective-c-associated-objects-implementation-principle>Objective-C Associated Objects 的实现原理</a>;
  2. <a href = http://www.jianshu.com/p/3cbab68fb856>给分类(Category)添加属性</a>;
  3. <a href = http://www.jianshu.com/p/535d1574cb86>iOS Category中添加属性和成员变量的区别</a>。

Github链接

<a href = https://github.com/JixinZhang/CategoryDemo/tree/master>查看代码请点击这里</a>

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

推荐阅读更多精彩内容

  • 转至元数据结尾创建: 董潇伟,最新修改于: 十二月 23, 2016 转至元数据起始第一章:isa和Class一....
    40c0490e5268阅读 1,633评论 0 9
  • 1.runtime体验 1.1.引言 运行时作为面试题中高阶问题必不可少的一个技能点。经常面试官会问道是否使...
    2897275c8a00阅读 854评论 0 5
  • 听说小北在德州又发烧了39度,在不停喝水的情况下,又退烧了,真是来的快,去的快! 最近半年多时间里,小北时不时的喊...
    海滨阅读 164评论 0 1
  • 文 陶蓉 有时候我就觉得绘本并不是孩子们的专利,大人一样适合。昨天出差途中,和同事聊起了春节,感慨现在过年的方式越...
    陶蓉子阅读 227评论 0 3
  • 预告,我现在脑子是空白的,这是一段漫无目的的流水账,写到我饿了就结束。 我有无数个在昨天给明天制定的计划,我羞愧告...
    植夫阅读 255评论 7 7