@selector() 与SEL 到底是啥

@selector() 与SEL 到底是啥

背景:

iOS 经常看到sdk中要传递个@selector,或者反射的时候也要这个,那这个到底是啥,今天我们从源码的角度来看下

测试代码

Objective-C
@autoreleasepool
        {
            SEL sel = @selector(abcefg);
    
        }

经过oc 转c++后看下到底是什么

xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main-arm64.cpp

 

C++
 { __AtAutoreleasePool __autoreleasepool; 
            SEL sel = sel_registerName("abcefg");
          
        }

也就是说@selector 转成c++ 后就变成了sel_registerName("abcefg");搞清楚这个东西sel_registerName ,也就找到了@selector 到底是啥了

sel_registerName

得益于objc4开源了,我们可以找到对应的源码

C++
SEL sel_registerName(const char *name) {
    return __sel_registerName(name, 1, 1);     // YES lock, YES copy
}
    static SEL __sel_registerName(const char *name, bool shouldLock, bool copy) 
    {
        SEL result = 0;
     
        if (shouldLock) selLock.assertUnlocked();
        else selLock.assertLocked();
     
        if (!name) return (SEL)0;
         //这个是重点
        result = search_builtins(name);
        if (result) return result;
        
        conditional_mutex_locker_t lock(selLock, shouldLock);
            auto it = namedSelectors.get().insert(name);
            if (it.second) {
                    // No match. Insert.
                    *it.first = (const char *)sel_alloc(name, copy);
            }
            return (SEL)*it.first;
    }
         static SEL search_builtins(const char *name) 
        {
        #if SUPPORT_PREOPT
          if (SEL result = (SEL)_dyld_get_objc_selector(name))
            return result;
        #endif
            return nil;
        }
         

上边源码可以看的出来sel_registerName->__sel_registerName->search_builtins->_dyld_get_objc_selector,而_dyld_get_objc_selector这个函数在objc4源码里边并没有,而是在dyld源码里边。

另外_dyld_get_objc_selector返回是空,还会走下边插入到h

https://opensource.apple.com/source/dyld/通过这个源码可以看到_dyld_get_objc_selector的实现,接下来我们就看看它的源码

_dyld_get_objc_selector

C++
const char* _dyld_get_objc_selector(const char* selName)
{
    log_apis("dyld_get_objc_selector()\n");
    return gAllImages.getObjCSelector(selName);
}

    const char* AllImages::getObjCSelector(const char *selName) const {
        if ( _objcSelectorHashTable == nullptr )
            return nullptr;
        return _objcSelectorHashTable->getString(selName, _objcSelectorHashTableImages.array());
    }
     
    const char* ObjCStringTable::getString(const char* selName, const Array<uintptr_t>& baseAddresses) const {
        StringTarget target = getPotentialTarget(selName);
        if (target == sentinelTarget)
            return nullptr;
     
        dyld3::closure::Image::ObjCImageOffset imageAndOffset;
        imageAndOffset.raw = target;
     
        uintptr_t sectionBaseAddress = baseAddresses[imageAndOffset.imageIndex];
     
        const char* value = (const char*)(sectionBaseAddress + imageAndOffset.imageOffset);
        if (!strcmp(selName, value))
            return value;
        return nullptr;
    }
     

通过这个返回值可以看出来SEL == const char* ,也就是oc方法去掉类型后的名字, 它会去找方法名字与dyld加载后的方法符号名字进行对比,如果是一样的就说明找到方法了,返回, 也就是@selector本质上就是找方法名字

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值