iOS weak关键字实现原理

2023-11-20

在iOS中,使用weak关键字能够对内存对象进行弱引用,基于这个特性,使用weak关键字能够解决许多问题,例如delegate中对象的循环持有问题、Block对对象的强引用导致的对象无法及时释放问题。

为何weak关键字能够实现对内存对象的弱引用,今天我们就来探究一下。

首先在分析weak关键字实现原理之前,先介绍一下相关的数据结构,这些数据结构其中一部分可能在其他地方有所提及,但本文只列出与weak关键字有关的一部分。

这些数据结构全部存在于runtime源码中,相关内容可以在 objc-weak文件中查看。

一、数据结构

1. SideTables

SideTables本质上是一个全局的 StripedMap

StripedMap本质是一个数组,且在iOS系统下,容量为64。

该数据结构通过实现[]操作,实现了类似字典的功能:可通过传入一个对象作为key值,来获取对应的Item。

SideTables中, Item类型为 SideTable,由此可见,对于任何一个对象, SideTables都能根据其地址对应到具体的一个 SideTable上。

2. SideTable

SideTable中包含三个元素,分别是 1.自旋锁 2.记录对象引用计数的字典 3.记录对象弱引用信息的数据结构 weak_table_t

其中 weak_table_t是与weak关键字有关的数据结构,其余二者暂可不用关注。

3. weak_table_t

weak_table_t本质上是一个数组,其中每个Item为 weak_entry_t

4. weak_entry_t

weak_entry_t就比较有意思了,它本质上是个字典。

其中的key值为对象,而value对应为一个数组,该数组最初为内部的一个大小为4的数组,当数组大小超过4后,则变为内部一个可变大小数组。

无论value值对应的数组是固定大小还是可变大小,数组中保存的值均为 weak_referrer_t类型的数据。

5. weak_referrer_t

weak_referrer_t本质上是 objc_object **,即Objective-C对象的地址。

所以,weak_entry_tvalue数组中,每一个Item均为一个地址,即weak对象的地址。

以上就是weak实现原理中所涉及到的所有数据结构,具体关系如下图:

Weak数据结构关系图

二、weak_table_tweak_entry_t相关方法

在正式探究weak关键字实现原理之前,先来看一些操作 weak_table_tweak_entry_t的方法。

1. 从 weak_table_t中查询对应的 weak_entry_t

static weak_entry_t *
weak_entry_for_referent(weak_table_t *weak_table, objc_object *referent)
{
    //获取weak_table_t的数组结构
    weak_entry_t *weak_entries = weak_table->weak_entries;

    if (!weak_entries) return nil;

    //获取对象地址,并根据地址映射到数组结构长度内,得到对应下标
    size_t index = hash_pointer(referent) & weak_table->mask;
    //线性探寻数组结构中对应的value所在index
    size_t hash_displacement = 0;
    while (weak_table->weak_entries[index].referent != referent) {
        index = (index+1) & weak_table->mask;
        hash_displacement++;
        if (hash_displacement > weak_table->max_hash_displacement) {
            return nil;
        }
    }
    
    //返回查询到的weak_entry_t
    return &weak_table->weak_entries[index];
}

2. 向 weak_table_t中增加新的 weak_entry_t

static void 
weak_entry_insert(weak_table_t *weak_table, weak_entry_t *new_entry)
{
    //获取weak_table_t的数组结构
    weak_entry_t *weak_entries = weak_table->weak_entries;
    assert(weak_entries != nil);

    //获取对象地址,并根据地址映射到数组结构长度内,得到对应下标
    size_t index = hash_pointer(new_entry->referent) & (weak_table->mask);
    //线性探寻数组结构中value所应在的位置
    size_t hash_displacement = 0;
    while (weak_entries[index].referent != nil) {
        index = (index+1) & weak_table->mask;
        hash_displacement++;
    }

    //将```weak_entry_t```放入```weak_table_t```对应位置,并更新相关数据
    weak_entries[index] = *new_entry;
    weak_table->num_entries++;

    if (hash_displacement > weak_table->max_hash_displacement) {
        weak_table->max_hash_displacement = hash_displacement;
    }
}

3. 扩展 weak_table_t容积

weak_entry_insert方法不需要考虑 weak_table_t容积,因为runtime代码中在调用 weak_entry_insert方法前都会调用 weak_grow_maybe方法来在必要的时候扩展 weak_table_t容积。

static void 
weak_grow_maybe(weak_table_t *weak_table)
{
    size_t old_size = TABLE_SIZE(w
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

iOS weak关键字实现原理 的相关文章

  • iOS app签名机制

    前言 在移动开发中 iOS系统下的app和andorid系统下的app一个很大的区别是 android系统下 app的安装很方便 可以从多个应用商店下载 小米应用商店 华为应用商店 也可以直接下载apk的包安装 而在iOS系统下 对app的
  • NSTextAttachment实现图文混排

    苹果在iOS7中推出了一个新的类NSTextAttachment 它是做图文混排的利器 本文就是用这个类 只用50行代码实现文字与表情混排 当然也可以实现段落中的图文混排 首先说一下文字和表情的混排 先来做点儿准备工作 搞一个存放表情信息的
  • iOS开发_HOOK

    我们在使用NSURLRequest时 传入请求地址URL 但是如果URL中有中文的话 我们会发现NSURLRequest的请求地址会报空 void viewDidLoad super viewDidLoad NSURL url NSURL
  • 将APP程序发布到iPhone或iPad上去测试

    转载至 http www appshare cn thread 3123 1 1 html 图文的介绍版本 http fstoke me blog tag apple 绝大多数iPhone Developer Distribution 的代
  • IOS 启动画面和图标设置(适配IOS7 and Xcode5)

    关于IOS程序设置启动画面以及图标的设备目前主要为 IPhone设备 和IPad设备 IPhone启动画面以及图标的设置 目前IPhone的分辨率为 320X480 640X960 640X1136 Default png 320X480
  • iOS开发环境xcode搭建

    1 到 https developer apple com download 或者在APP store下载 2 下载完成后会在launchpad显示 点击安装
  • ios-常见的命令行工具

    pwd 查看当前目录 cat 在命令行中查看文件 ls 查看文件 ls l 就是以列表的形式展开 touch 创建文件 open 打开文件 more 分页查看文件内容 f是下一页 b是上一页 当你命令行有很多东西你写错了的时候不想去一一删除
  • iOS-Andriod百度地图仿百度外卖-饿了么-选择我的地址-POI检索/

    http zanderzhang gitcafe io 2015 09 19 iOS Andriod百度地图仿百度外卖 饿了么 选择我的地址 POI检索 title iOS Andriod百度地图仿百度外卖 饿了么 选择我的地址 POI检索
  • 一个奇怪的GCD内存不释放的问题

    这个问题是我的同学提出来的 原帖在http bbs csdn net topics 390933411 大概是这样 pre class objc IBAction touchToCreateThread id sender int i 10
  • APP开发如何批量生成不同尺寸的图标?

    在我们开发APP的时候 我们使用到大量的不同尺寸的APPLogo的图片 如下图 通常 我们的做法是和设计师沟通 让他们切出这儿所以的图片 然后我们一个一个图片放在对应的位置 这样处理的话 我们比较容易出错 比如说 图片的格式 苹果对图片的格
  • iOS左对齐自动换行collection样式

    前言 想必大家工作中或多或少会遇到下图样式的UI需求吧 像这种cell长度不固定 以此向右对齐排列的样式UI可以说是很常见的 实现方式 一般的实现可能主要是分一下两种 1 一种是用button依次排列实现 动态计算text宽度 记录之前一个
  • iOS App上架流程

    前言 作为一名IOS开发者 把开发出来的App上传到App Store是必须的 下面就来详细介绍下具体流程 1 打开苹果开发者中心 https developer apple com 打开后点击 Member Center 如果你的电脑没有
  • UITableView性能优化-一次面试后的反思总结

    面试的时候遇到这个问题 竟一时没有全答上来 于是Google了一下 常见的一些譬如Cell重用 设计统一Cell 缓存Cell高度 Cell数据资源缓存 这些其实平时都在用 但因为平时还是缺乏总结 回答这么个问题的时候却只想到说 重用 缓存
  • 【ios开发技术】Swift 语言深入--Swift设计模式 (2/2)

    Getting Started 让我们开始 你可以下载the project source from the end of part 1与我们共同来探索 这是你在第一部分结束时完成的音乐库App样品 应用程序的最初设计包括在屏幕的顶端上上水
  • Xcode5.1离线下载安装及使用iOS5模拟器进行开发调试的方法

    Xcode5 1默认不支持iOS5版本的模拟器开发调试 在OS X Mavericks 10 9 x 下默认只能支持iOS6 1及以上版本的模拟器 在OS X Mountain Lion 10 8 x 下默认只能支持iOS6 0及以上版本的
  • ios开发教程入门到精通

    第1集 初识macOS 点击观看 第2集 开发工具Xcode 点击观看 第3集 初识Objective C 点击观看 待续
  • iOS下XMPP开发之XMPP开发环境配置(二)mac上搭建openfire服务器

    一 下载并安装openfire 1 到http www igniterealtime org downloads index jsp下载最新openfire for mac版 比如 Openfire 3 8 1 下载后的文件 openfir
  • iOS开发,tableView中cell的重用详解

    注意 原创版权 转载必须标明出处作者 翻版必究 iOS中tableView是一个大的模块组件 它的重要性每个iOSCoder都是了解的 但是tableView中却有个重大的坑 就是cell的重用 每个刚接触iOS开发的人都深受其海 那么经过
  • iOS中自动消失提示框的实现

    iOS中自动消失提示框的实现 添加一个提示框 UIAlertView alert UIAlertView alloc initWithTitle 提示 message 你很漂亮 delegate self cancelButtonTitle
  • 探究Xcode New Build System对于构建速度的提升

    在Xcode9发布的时候 Apple在Build System上提供了新版本的构建系统 New Build System 具体可见WWDC2017 不过令人失望的是 该新特性的讲解很简短 短到只在一页PPT上露脸 在这短短的时间里 苹果讲述

随机推荐