开头先说明一下,之所以把这二者放在一起比较,是因为今天看到了一个很有趣的写法
- (void)setLk_imageInfo:(LKImageInfo *)imageInfo
{
objc_setAssociatedObject(self, @selector(setLk_imageInfo:), imageInfo, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
我们都知道,在OC中如果想给分类添加属性@property
是不能直接生成对应的setter
和getter
的而且即使手写setter
和getter
也不能使用实例变量,所以只能通过runtime
中这种关联的形式来绑定特定对象。
再来看一下objc_setAssociatedObject
的定义:
objc_setAssociatedObject(id _Nonnull object, const void * _Nonnull key,
id _Nullable value, objc_AssociationPolicy policy)
可以看到第二个参数key
需要一个 const void *
类型的参数作为绑定的key,以往我在使用这个方法的时候都会自己生成一个key,而今天看到的代码中则使用了@selector(setLk_imageInfo:)
,传入了一个SEL
,对此我也做了简单的实验。
先来看一下SEL
的定义:
/// An opaque type that represents a method selector.
typedef struct objc_selector *SEL;
可以看到SEL
是一个结构体指针,而 const void *
是一个无类型指针常量,所以从 SEL -> const void*
来赋值是说得通的,但是如果想反过来使用是不可以的。
const void *sel = @selector(beginTimer);
Obj *obj = [Obj new];
[obj performSelector:sel];
最开始对sel的赋值并不会有警告,因为void*本身就是无类型,但是这段代码将无法执行并且报错。
最后,今天也算是学到了一个写关联的时候偷懒的好方法:D。
网友评论