当前位置: 首页 > wzjs >正文

微信微网站开发报价石家庄网站建设就找企行家

微信微网站开发报价,石家庄网站建设就找企行家,为什么营销型网站比普通网站建站贵,做网站需要懂什么技术「OC」源码学习——alloc与init的实现 前言 费劲千辛万苦终于项目给写完了,进入下一个阶段,源码的学习 alloc的调用顺序 我们在main函数之中打上断点,先运行 再在alloc之中的各个函数之中打上断点,在关键步骤上打上断点&#…

「OC」源码学习——alloc与init的实现

前言

费劲千辛万苦终于项目给写完了,进入下一个阶段,源码的学习

alloc的调用顺序

我们在main函数之中打上断点,先运行

image-20250422120724912

再在alloc之中的各个函数之中打上断点,在关键步骤上打上断点,我们可以,很容易总结出我们alloc源码的编译流程。

先说结论,编译的具体流程如下

1487527-bc778871d88fdd22

流程探究

接下来我们在按照这个顺序进行断点调试,我们现在allocobjc_alloc处打一个断点,运行程序,我们会发现我们的断电先停在的是objc_alloc内,查看网上的资料,这是因为LLVM 在编译阶段会将 alloc 符号替换为 objc_alloc 入口点。

image-20250423114756417

接着继续步入,断点情况如下

image-20250423115300414

进入alloc流程之中的核心callAlloc,对两个return打上断点,我们可以看到,自定义类在第一次进入callAlloc的时候,是会使用消息转发的方法,再去调用真正的alloc函数

image-20250423120018851

至于为何需要走两次callAlloc的原因我们先按下不表,接着程序再次调用callAlloc,这次我们会发现断点打在了_objc_rootAllocWithZone之中

请添加图片描述

进入函数看看
image-20250423194828460

这个函数内容过于复杂,等到下一篇文章再详细阐述,我们只要知道,这个程序是动态创建类实例的核心函数,用于分配内存并初始化实例的 isa 指针。

Objective-C 中自定义类的 alloc 方法调用流程涉及双重 callAlloc 的机制,其根源在于 类初始化延迟运行时多态性设计。以下是该流程的核心原因及分步解析:

1. 首次调用 objc_alloc
  • 入口id objc_alloc(Class cls) 是运行时提供的全局分配函数。
  • 目的
    • 检查类是否已初始化(cls->isRealized())。
    • 若未初始化,触发 class_initialize() 完成类加载。
2. 进入 callAlloc
  • 参数checkNil=trueallocWithZone=false
  • 逻辑
    • 检查类是否存在(slowpath(checkNil && !cls))。
    • 若类支持优化路径(未重写 allocWithZone:),直接调用 _objc_rootAllocWithZone
3. 动态派发 objc_msgSend
  • 触发条件:若类重写了 allocWithZone:,需通过消息发送调用自定义逻辑。
  • 结果:进入类的 +alloc 方法,最终再次调用 callAlloc
4. 第二次 callAlloc
  • 参数checkNil=falseallocWithZone=true
  • 逻辑
    • 直接调用 _objc_rootAllocWithZone,跳过安全检查。
    • 最终通过 _class_createInstanceFromZone 完成内存分配和 isa 绑定。

两次进入的区别

我们现在在来看看两次进入callAlloc究竟有什么区别

第一次调用 callAlloc 时,参数 checkNil=true,在程序之中需要验证类是否存在。

image-20250424121010777

第二次调用 callAlloc 时,参数 checkNil=false,跳过安全检查。

image-20250424121031770

其实差别就在于,后面传进的两个布尔值,其实就是是否需要进行安全检查。在第一次进入callAlloc会做一次检查,确保对应的类不为空。

为何自定义类需要进入两次callAlloc

static ALWAYS_INLINE id
callAlloc(Class cls, bool checkNil, bool allocWithZone=false)
{if (slowpath(checkNil && !cls)) return nil;if (fastpath(!cls->ISA()->hasCustomAWZ())) {return _objc_rootAllocWithZone(cls, nil);}// No shortcuts available.if (allocWithZone) {return ((id(*)(id, SEL, struct _NSZone *))objc_msgSend)(cls, @selector(allocWithZone:), nil);}return ((id(*)(id, SEL))objc_msgSend)(cls, @selector(alloc));
}

系统类(如 NSObject):

因为NSObject在编译时已完成isa指针的初始化。所以不需要经过两次callAlloc

只需要直接进入objc_alloc->callAlloc->_objc_rootAllocWithZone直接申请空间即可

自定义类:

  • 第一次 callAlloc 通过 objc_alloc 进入,目的是 检查类的初始化状态,类初次创建是没有默认的alloc/allocWithZone实现的所以继续向下执行进入到msgSend消息发送流程,为这个类进行初始化。

  • 第二次 callAlloc,此时类已初始化完成,进入实际内存分配逻辑。

  • callAlloc 的分支逻辑

    if (fastpath(!cls->ISA()->hasCustomAWZ())) {return _objc_rootAllocWithZone(cls, nil); // 直接分配内存
    } else {return objc_msgSend(cls, @selector(alloc)); // 通过消息发送调用自定义逻辑
    }
    
    • hasCustomAWZ():检测类是否重写了 allocWithZone: 方法。
    • 若未重写(默认情况),直接调用 _objc_rootAllocWithZone 分配内存。
    • 若重写,则通过 objc_msgSend 触发动态派发,确保调用正确的 alloc 实现。

    那么源码是如何查看缓存的呢,我们进入hasCustomAWZ()看一下

    #   define FAST_CACHE_HAS_DEFAULT_AWZ    (1<<14)
    bool hasCustomAWZ() const {return !cache.getBit(FAST_CACHE_HAS_DEFAULT_AWZ);}bool getBit(uint16_t flags) const {return _flags & flags;}
    

    FAST_CACHE_HAS_DEFAULT_AWZ宏定义表示 是否实现alloc/allocWithZone位域标识位

    为了证明是类没有初始化的问题才导致callAlloc函数在类第一次被调用的时候被进入两次,我们可以通过在申请一次空间来尝试一下,断点和之前的一样。

    GGObject *obj = [GGObject alloc];
    GGObject *obj2 = [GGObject alloc];
    

    image-20250424141439512

    我们发现obj2的alloc调用顺序就和NSObject一样了。objc_alloc->callAlloc->_objc_rootAllocWithZone

    但紧接着问题又来了,重复进入callAlloc的原因我们找到了,那为什么要设置这个流程,这个所谓的类初始化实在哪里开始的呢?

    查看hasCustomAWZ()的调用栈可以看到,有个名字为 _objc_msgSend_uncached的方法,其实也很好理解,就是消息发送给了一个初始化信息的类之中,其实就是在消息转发这一步顺带把第一次调用的类进行初始化,然后在第二次进入hasCustomAWZ()就能进入

    _objc_rootAllocWithZone

image-20250424132737830

双重 callAlloc 流程是 Objective-C 运行时与编译器协作的产物,其核心目的是 确保类初始化完成兼容自定义内存分配逻辑。这一机制平衡了性能、灵活性与安全性,是 Objective-C 动态特性的典型体现。

init

其实点进去init, 很简单,就是把内容返回一次,如此设计的原因是为了让整个程序符合工厂模式的设计理念,我们可以通过简单的重新init的方法去实现较为复杂的其他操作。

image-20250424164807997

总结

其实我是想讲整一个alloc的流程梳理完整再将内容发出,无奈一个完完整整的流程涉及的内容实在过多,有想要了解的可以看 OC对象底层内存开辟和实现(中)了解初始化类的完整流程

参考资料

iOS-底层原理 02:alloc & init & new 源码分析

iOS-底层原理 04:NSObject的alloc 源码分析

OC对象底层内存开辟和实现(中)


文章转载自:

http://Y7VC39BD.nwtkz.cn
http://kH244pBk.nwtkz.cn
http://fOqD4lv1.nwtkz.cn
http://AVJeeQct.nwtkz.cn
http://4BqNCYy8.nwtkz.cn
http://0meo72vP.nwtkz.cn
http://PSaHSr2l.nwtkz.cn
http://RuS1BZBC.nwtkz.cn
http://lTWGOVVI.nwtkz.cn
http://m12cUhf0.nwtkz.cn
http://YY2FeOB6.nwtkz.cn
http://kgbZvTYE.nwtkz.cn
http://hQYWYuaY.nwtkz.cn
http://H3RtV5GE.nwtkz.cn
http://PKl904iz.nwtkz.cn
http://5wtkLKkm.nwtkz.cn
http://dH6PukMM.nwtkz.cn
http://LyDnb2uF.nwtkz.cn
http://E4VIQXrV.nwtkz.cn
http://ekZqYVNl.nwtkz.cn
http://G8Na4pfx.nwtkz.cn
http://s6C6jpQt.nwtkz.cn
http://23miE08y.nwtkz.cn
http://SYDymswb.nwtkz.cn
http://FHCsZAM1.nwtkz.cn
http://waHS3xSK.nwtkz.cn
http://falMRP6S.nwtkz.cn
http://EVXd8xQS.nwtkz.cn
http://S3do6OGg.nwtkz.cn
http://xpfvabAr.nwtkz.cn
http://www.dtcms.com/wzjs/740915.html

相关文章:

  • 校园官方网站建设的书籍现在公众号做电影网站的发展
  • 国家城乡建设官方网站做任务挣钱网站
  • 微网站免费建站系统网络设置网址
  • 网站关键字优化网页制作ppt教学课件
  • 深圳宝安区住房和建设局网站官网物流网站大全
  • 做自己的首席安全官的网站海南跨境免税电商入驻流程
  • 网站加速器怎么开做死活题网站
  • 虚拟空间做网站网站地图类型
  • 柯桥区交通投资建设集团网站中介网站开发
  • wordpress图片优化唐山百度搜索排名优化
  • 网站seo 教程规模以上工业企业划分标准
  • 做电气设计有哪些好的网站推广普通话奋进新征程手抄报
  • 软件网站建设专业城市介绍网站模板
  • 龙岗网站网页统计代码大全
  • 学校网站建设工作计划河南中州路桥建设有限公司网站
  • 个人网站开发的意义网站群集约化建设
  • 创建网站用什么语言怎么制作网站获取他人ip
  • 电子商务与网站建设策划书网站安全建设需求分析报告
  • 网站建设开发公司有哪些淘宝店铺首页设计
  • 有哪些网站是做视频的国外的app设计网站
  • 广西网站建设建议建设一个门户网站
  • 模版建网站更换wordpress字体
  • 网站发布 图片看不到推广平台软件有哪些
  • 网站开发协助方案长沙网站建设哪个好
  • 建模素材免费网站今天发生的重大新闻内容
  • 手表二级市场网站做网站如何用代码把字体变大
  • dw网站建设教程做评测好的视频网站
  • 做一个网站需要哪些资源做网站的女生多么
  • 小白如何做网站建设公众号萍乡建设网站
  • 高中网站建设计划表深圳专业网站建设平台网页