特性
objective-c中,有类别可以在不修改源码的基础上增加方法;近排在看别人的开源代码时,发现还可以动态增加属性。而且是在运行时,太牛B了。
使用运行时库,必须要先引入 objc/runtime.h
可以使用的函数如下:
OBJC_EXPORT void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
创建关联要使用到Objective-C的运行时函数:objc_setAssociatedObject来把一个对象与另外一个对象进行关联。该函数需要四个参数:源对象,关键字,关联的对象和一个关联策略。当然,此处的关键字和关联策略是需要进一步讨论的。
关键字是一个void类型的指针。每一个关联的关键字必须是唯一的。通常都是会采用静态变量来作为关键字。
关联对象可以作为作为一个让源对象持有这个关键对象的方法(相当于将关键对象通过源对象传递),比如下面的label中的颜色,其中的objc_setAssociatedObject是将关联的对象传出,通过方法objc_getAssociatedObject(id object, const void *key) 获取到,例如下面的View中的block,是将block在objc_setAssociatedObject中定义,而在objc_getAssociatedObject得到block后实现。
关联策略表明了相关的对象是通过赋值,保留引用还是复制的方式进行关联的;还有这种关联是原子的还是非原子的。这里的关联策略和声明属性时的很类似。这种关联策略是通过使用预先定义好的常量来表示的。
这个函数
OBJC_EXPORT id objc_getAssociatedObject(id object, const void *key)
__OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_1);
使用场景
1.category使用 objc_setAssociatedObject/objc_getAssociatedObject 实现添加属性
属性 其实就是get/set 方法。我们可以使用 objc_setAssociatedObject/objc_getAssociatedObject 实现 动态向类中添加 方法
UILabel+Associate.h
#import <UIKit/UIKit.h>
@interface UILabel (Associate)
- (void) setFlashColor:(UIColor *) flashColor;
- (UIColor *) getFlashColor;
@end
UILabel+Associate.m
#import"UILabel+Associate.h"
#import<object/runtime.h>
@implementationUILabel (Associate)
static char flashColorKey;
- (void) setFlashColor:(UIColor *) flashColor{
objc_setAssociatedObject(self,&flashColorKey, flashColor, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (UIColor *) getFlashColor{
return objc_getAssociatedObject(self, &flashColorKey);
}@end
调用代码:
UILabel *lab =[[UILabel alloc] init];
[lab setFlashColor:[UIColor redColor]];
NSLog(@"%@", [lab getFlashColor]);
2.objc_setAssociatedObject与Block的简单使用
UIAlertView的扩展
.h文件
#import <UIKit/UIKit.h>
typedf void(^successBlock)(NSInteger buttonIndex);
@interface UIAlertView(Block)
- (void)showWithBlock:(successBlock)block;
@end
.m文件
#import"UIAlertView+Block.h"
#import
static const char alertKey;
@implementationUIAlertView(Block)
- (void)showWithBlock:(successBlock)block{
if(block) {
objc_setAssociatedObject(self, &alertKey, block, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
self.delegate=self;
}
[self show];}
- (void)alertView:(UIAlertView*)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{ successBlock block = objc_getAssociatedObject(self, &alertKey);
block(buttonIndex);}
@end
UIButton的扩展
.h文件
#import
typedef void(^btnBlock)();
@interfaceUIButton(Block)
- (void)handelWithBlock:(btnBlock)block;
@end
.m文件
#import"UIButton+Block.h"
#import <objc/runtime.h>
static const char btnKey;
@implementationUIButton(Block)
- (void)handelWithBlock:(btnBlock)block{
if(block) {
objc_setAssociatedObject(self, &btnKey, block, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
[self addTarget:selfaction:@selector(btnAction) forControlEvents:UIControlEventTouchUpInside];
}
- (void)btnAction{
btnBlock block = objc_getAssociatedObject(self, &btnKey);
block();
}
@end
这两个方法可以让一个对象和另一个对象关联,就是说一个对象可以保持对另一个对象的引用,并获取那个对象。有了这些,就能实现属性功能了。 policy可以设置为以下这些值: