File tree Expand file tree Collapse file tree
2024/12/11/iOS/2024 再探ObjC-Category:动态特性与运行时实现的极致之美 Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -53,7 +53,7 @@ <h2 id="Category-之运行时实现细节:探索内部实现原理"><a href="#
5353< p > 在 rwe 这个对象中拥有三个变量,分别是:方法列表、属性列表、协议列表,这个变量其实就是一个二维数组。以方法列表为例,类自身的所有方法是一个数组,每个 Category 中的所有方法是一个数组,它们都被放在这个二维数组中,注意,类自身的方法列表放在这个二维数组的最后面,最后编译的那个 Category 中的方法列表放在这个二维数组的最前面。</ p >
5454< p > 正是因为这个特点才导致了 Category 中的方法实现会覆盖与类本身同名的方法实现。所以,在开发过程中我们经常会看到很多框架都会给 Category 的方法和属性添加前缀,其目的就是为了降低重名的可能性。</ p >
5555< p > 有些人说 Category 不支持添加实例变量是因为 < code > category_t</ code > 结构体中没有 < code > ivars</ code > 字段。其实并不是添加一个字段的事,根本原因是因为开发者可能会用 Category 给已经编译好的类(例如系统类)添加数据,而这些类的内存布局与地址已经固定死了,如果要给它添加实例变量势必要修改其内存布局与地址。</ p >
56- < p > 另外,也不能给 Category 添加 weak 属性,如果一定要添加 weak 属性的话,可以采用中间者模式,即给 Category 添加一个中间者对象,然后给这个中间类声明一个 weak 属性。关于 weak 指针的更多细节请看我的另一篇文章 < a href ="https://budo.top/ 2023/10/21/iOS/%E6%8F%AD%E5%BC%80%20iOS%20%E4%B8%AD%20weak%20%E6%8C%87%E9%92%88%E7%9A%84%E7%A5%9E%E7%A7%98%E9%9D%A2%E7%BA%B1%EF%BC%9A%E4%BB%8E%E5%8E%9F%E7%90%86%E5%88%B0%E5%AE%9E%E8%B7%B5" > 深入理解iOS中的 weak 指针 </ a > 。 </ p >
56+ < p > 另外,也不能给 Category 添加 weak 属性,如果一定要添加 weak 属性的话,可以采用中间者模式,即给 Category 添加一个中间者对象,然后给这个中间类声明一个 weak 属性。关于 weak 指针的更多细节请看我的另一篇文章 < a href ="/ 2023/10/21/iOS/%E6%8F%AD%E5%BC%80%20iOS%20%E4%B8%AD%20weak%20%E6%8C%87%E9%92%88%E7%9A%84%E7%A5%9E%E7%A7%98%E9%9D%A2%E7%BA%B1%EF%BC%9A%E4%BB%8E%E5%8E%9F%E7%90%86%E5%88%B0%E5%AE%9E%E8%B7%B5/ " title =" 揭开 iOS 中 weak 指针的神秘面纱:从原理到实践 " > 揭开 iOS 中 weak 指针的神秘面纱:从原理到实践 </ a > </ p >
5757< p > 我在网上看到有些人说为什么要把 Category 设计成使用 Runtime 运行时加载,直接设计成编译时加载不是更好吗?他们的想法是:“在给项目中某个类(这个类是在项目中创建的),例如 CustomClass 创建分类时,编译器其实能拿到 CustomClass 的实现文件,那么只要把分类中的方法和这个类自身的方法合并不就行了,这样还能实现在 Category 中给这个类添加实例变量。” 乍一看没啥问题。但是,Category 还支持给已经编译好的类(例如系统类)添加方法实现,而这些类的布局和地址已经固定死了,因而不能这么干。</ p >
5858< p > 在阅读源码的过程中,我还发现了一些其它问题:</ p >
5959< ol >
Original file line number Diff line number Diff line change @@ -24,7 +24,6 @@ <h2 id="个人简介"><a href="#个人简介" class="headerlink" title="个人
2424< h2 id ="网络信息 "> < a href ="#网络信息 " class ="headerlink " title ="网络信息 "> </ a > 网络信息</ h2 > < ul >
2525< li > 个人邮箱:< a href ="mailto:internetwei@foxmail.com "> internetwei@foxmail.com</ a > </ li >
2626< li > Github: < a target ="_blank " rel ="noopener " href ="https://github.com/internetwei "> https://github.com/internetwei</ a > </ li >
27- < li > Gitee: < a target ="_blank " rel ="noopener " href ="https://gitee.com/internetwei "> https://gitee.com/internetwei</ a > </ li >
2827< li > 掘金:< a target ="_blank " rel ="noopener " href ="https://juejin.cn/user/2418581312385288/posts "> https://juejin.cn/user/2418581312385288/posts</ a > </ li >
2928</ ul >
3029</ div > </ article > < nav id ="pagination "> < div class ="pagination "> </ div > </ nav > < div id ="lv-container " data-id ="city " data-uid ="MTAyMC81MzU5Ny8zMDA3MA== "> < script > ( function ( d , s ) {
Load Diff Large diffs are not rendered by default.
Load Diff Large diffs are not rendered by default.
You can’t perform that action at this time.
0 commit comments