• @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& 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本质上就是找方法名字

  • 相关阅读:
    【如何学习CAN总线测试】——AUTOSAR网络管理测试
    自动控制原理7.5---离散系统的稳定性与稳态误差
    SQL教程之 开始学习用于数据分析的的五个SQL 命令 (教程含源码)
    视频分割合并工具说明
    CSS时间线样式
    javaH5女娲宫旅游网站设计与实现计算机毕业设计MyBatis+系统+LW文档+源码+调试部署
    HTML期末学生大作业 基于HTML+CSS+JavaScript通用的后台管理系统ui框架模板
    快如闪电的扩容:秒级启动,弹性伸缩让您无忧
    猿创征文|我与开发工具的那些事
    java毕业设计家教管理系统mybatis+源码+调试部署+系统+数据库+lw
  • 原文地址:https://blog.csdn.net/c553110519/article/details/126597666