OC中的SEL與C中的const void *

weixin_34075551發表於2018-03-07

開頭先說明一下,之所以把這二者放在一起比較,是因為今天看到了一個很有趣的寫法

- (void)setLk_imageInfo:(LKImageInfo *)imageInfo
{
    objc_setAssociatedObject(self, @selector(setLk_imageInfo:), imageInfo, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

我們都知道,在OC中如果想給分類新增屬性@property是不能直接生成對應的settergetter的而且即使手寫settergetter也不能使用例項變數,所以只能通過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。

相關文章