Open yidaizhenlong opened 10 years ago
我用UIAlertview来示例关联与方法交换。如果要给UIAlertview加上一个block 的点击事件,一般的做法是重写UIAlertview,在子类中加上点击的block。这样耦合度太高了,如果我们能够写一个category实现alertview的点击block 就好了,但是category是不允许属性的,所以我们得用另外一种方式实“现曲线救国”。下面我将以采访的口吻聊一聊关联与方法交换。 我: " 下面有请我们的“关联君”登场。" 关联君:"大家好,我是关联君,你只要在工程里面#import <objc/runtime.h>,就可以召唤我了,我的主要作用是扩展属性哦。使用我可以使得你高端大气上档次,低调奢华有内涵哦。" 看到关联君没停的意思,我慌忙打断他:“那个,问下,为什么我很少见到别人使用你呢?” “这。。呵呵”关联君尴尬的说道“人艰不拆嘛,你这个博主太没礼貌了!不过看在你虚心求教技术的份上我就告诉你吧,我的主要使用地方是当属性和全局变量不能使用的时候,说白了就是在我配合category会更好的效果,为什么?因为使用我需要key值,一般是一个不可变的字符串,如果在一类中大量的调用我会产生很多不同的key值,这样不便于维护。所以好钢用在刀刃上,用我就要关键地方哦” 我:“那你能仔细说说我们该怎么使用你呢?” 关联君整理了下衣服,一本正经的说道:“首先呢需要调:objc_setAssociatedObject(id object, const void key, id value, objc_AssociationPolicy policy)这方法关联你需要关联的对象,第一个参数是传入:调用我的类,常见的是self,第二参数要传一个关联的key值以方便你取出来,有点类似,字典的key和广播的Name,第三个参数要传入的就是你要关联的对象,最后一个参数是传入你你想关联的方式,有简单的ASSIGN,COPY_NONATOMIC,RETAIN_NONATOMIC,retian,和copy,是不是看上去跟属性很像呢?第二步就是获取扩展属性了,使用 objc_getAssociatedObject(id object, void key) ,娶我,不对是取我就容易多了,只需传入调用我的类,和相应地key就可以去到你想取的对象了。” 突然想到一个问题,我就弱弱的问关联君:“那怎么释放你呢?” 关联君一下子脸黑了:“你这个娃娃,怎么这么不懂事,上来就问我怎么死,好了的,看在你求知识份上,我大发慈悲的告诉你,有两个办法,第一调用objc_removeAssociatedObjects(id object)方法就可以删除指定对象实例的所有扩展属性,注意哦是所有哦,第二种是删除某一个扩展属性,这要个小技巧哦,调用objc_setAssociatedObject 传入nil就可以了哦,示例下:objc_setAssociatedObject(self, &key, nil, OBJC_ASSOCIATION_ASSIGN); (鉴于关联对象设置为了 nil,policy也就是第四个参数实际上不再重要) 打断对象的所有关联可以用objc_removeAssociatedObjects,总的来说,不提倡打断对象的所有关联,除非你希望对象回到原始状态。”
我用UIAlertview来示例关联与方法交换。如果要给UIAlertview加上一个block 的点击事件,一般的做法是重写UIAlertview,在子类中加上点击的block。这样耦合度太高了,如果我们能够写一个category实现alertview的点击block 就好了,但是category是不允许属性的,所以我们得用另外一种方式实“现曲线救国”。下面我将以采访的口吻聊一聊关联与方法交换。 我: " 下面有请我们的“关联君”登场。" 关联君:"大家好,我是关联君,你只要在工程里面#import <objc/runtime.h>,就可以召唤我了,我的主要作用是扩展属性哦。使用我可以使得你高端大气上档次,低调奢华有内涵哦。" 看到关联君没停的意思,我慌忙打断他:“那个,问下,为什么我很少见到别人使用你呢?” “这。。呵呵”关联君尴尬的说道“人艰不拆嘛,你这个博主太没礼貌了!不过看在你虚心求教技术的份上我就告诉你吧,我的主要使用地方是当属性和全局变量不能使用的时候,说白了就是在我配合category会更好的效果,为什么?因为使用我需要key值,一般是一个不可变的字符串,如果在一类中大量的调用我会产生很多不同的key值,这样不便于维护。所以好钢用在刀刃上,用我就要关键地方哦” 我:“那你能仔细说说我们该怎么使用你呢?” 关联君整理了下衣服,一本正经的说道:“首先呢需要调:objc_setAssociatedObject(id object, const void key, id value, objc_AssociationPolicy policy)这方法关联你需要关联的对象,第一个参数是传入:调用我的类,常见的是self,第二参数要传一个关联的key值以方便你取出来,有点类似,字典的key和广播的Name,第三个参数要传入的就是你要关联的对象,最后一个参数是传入你你想关联的方式,有简单的ASSIGN,COPY_NONATOMIC,RETAIN_NONATOMIC,retian,和copy,是不是看上去跟属性很像呢?第二步就是获取扩展属性了,使用 objc_getAssociatedObject(id object, void key) ,娶我,不对是取我就容易多了,只需传入调用我的类,和相应地key就可以去到你想取的对象了。” 突然想到一个问题,我就弱弱的问关联君:“那怎么释放你呢?” 关联君一下子脸黑了:“你这个娃娃,怎么这么不懂事,上来就问我怎么死,好了的,看在你求知识份上,我大发慈悲的告诉你,有两个办法,第一调用objc_removeAssociatedObjects(id object)方法就可以删除指定对象实例的所有扩展属性,注意哦是所有哦,第二种是删除某一个扩展属性,这要个小技巧哦,调用objc_setAssociatedObject 传入nil就可以了哦,示例下:objc_setAssociatedObject(self, &key, nil, OBJC_ASSOCIATION_ASSIGN); (鉴于关联对象设置为了 nil,policy也就是第四个参数实际上不再重要) 打断对象的所有关联可以用objc_removeAssociatedObjects,总的来说,不提倡打断对象的所有关联,除非你希望对象回到原始状态。”