返回

深入探讨 iOS weak 底层原理

IOS

一抹暖意——深入探讨iOS weak底层原理

我们一直都很熟悉Objective-C,对strong,retain,release也很熟悉,

在swift出来之后,weak,unsafe_unretained这些新东西,尤其unsafe_unretained的概念也比较难以理解。

但是,如果我们真的想要搞懂内存管理,就必须搞明白weak,unsafe_unretained到底是什么。

关于unsafe_unretained我们后续说,现在我们首先讨论一下weak,我们利用类比的方式,回顾下release和retain。

retain的概念如同向银行存钱,release就是从银行取钱。

weak是什么?

weak是另外一种关系,我们简单看下它的定义,weak的英文是虚弱、脆弱的,这里我们也可以理解为指向内存地址的引用发生关系。

weak和strong的区别

  1. weak可以为nil,而strong肯定是有值的。
  2. weak对象指向的内存如果释放了,weak的指针会自动变成nil,而strong会引发crash。

我们继续看下weak的底层原理。

weak底层原理

strong会引用到对象头中的isa指针,而weak不会,weak指针的结构和strong指针完全不一样,引用的是ISA指针之后的指针,如下图:

struct WK {
   void * isa;
   void * newIsa;
};

weak指针是只读的,结构体只有get没有set方法。

weak的引用计数

前面我们说weak会把指针指向isa之后的指针,同时weak还维护了一个引用计数,这个引用计数不是指向对象本来的引用计数,而是用来记录有多少个weak指向的对象。

当weak指向的对象被释放时,weak会自动将对象地址置为nil,同时将引用计数置为0,而weak引用对象的isa指针仍然指向当前对象,不会改变。

weak对内存管理至关重要,内存管理的核心就是管理指针,减少野指针的产生。

weak的用法

weak主要用于修饰实例变量,当weak修饰的实例变量所指向的对象被释放后,weak指向的对象会被自动设置为nil。这可以防止野指针的产生,避免程序崩溃。

弱引用的优点

  1. 可以避免野指针的产生。
  2. 可以提高程序的健壮性。
  3. 可以减少内存泄漏的风险。

弱引用的缺点

  1. 只能用于实例变量。
  2. 不能用于修饰全局变量。
  3. 不能用于修饰静态变量。
  4. 不能用于修饰局部变量。

weak的注意事项

  1. weak指针不能用作参数传递。
  2. weak指针不能用作方法的返回值。
  3. weak指针不能用作属性的类型。
  4. weak指针不能用作协议的类型。

weak应用场景

  1. 避免野指针的产生。
  2. 防止程序崩溃。
  3. 减少内存泄漏的风险。
  4. 实现循环引用。

结语

weak是iOS开发中非常重要的一个概念,理解了weak的原理和用法,可以帮助我们更好地进行内存管理,避免野指针的产生,提高程序的健壮性。