编程进阶网 编程进阶网
首页
  • 计算机原理
  • 操作系统
  • 网络协议
  • 数据库原理
  • 面向对象
  • 设计原则
  • 设计模式
  • 系统架构
  • 性能优化
  • 编程原理
  • 方案设计
  • 稳定可靠
  • 工程运维
  • 基础认知
  • 线性结构
  • 树与哈希
  • 工业级实现
  • 算法思想
  • 实战与综合
  • 算法题考核
  • C语言入门
  • C综合案例
  • C专栏博客
  • C标准集库
  • C++入门教程
  • C++综合案例
  • C++专栏博客
  • C++开发技巧
  • Java入门教程
  • Java综合案例
  • Java专栏博客
  • Go入门教程
  • Go综合案例
  • Go专栏博客
  • Go开发技巧
  • JavaScript入门
  • JavaScript高级
  • Android库解读
  • Android专栏
  • Android智能硬件
  • iOS ObjC入门
  • iOS Swift入门
  • iOS入门精通
  • Web之Html手册
  • Web之TypeScript
  • Web之Vue高级进阶
  • Linux之QML入门
  • Linux之QT核心库
  • Linux实践开发
  • Python教程
  • Shell&Bash教程
  • 工具脚本
  • 自动化脚本
  • 质量保障
  • 产品思考
  • 软实力
  • 开发流程
  • Git应用
  • 技术模版
  • 技术规范
  • Markdown
  • Mermaid
  • 开源协议
  • JSON工具
  • 文本工具
  • 图片处理
  • 文档转化
  • 代码压缩
  • 关于我
  • 自我精进
  • 职场管理
  • 职场面试
  • 心情杂货
  • 友情链接

杨充

专注编程 · 终身学习者
首页
  • 计算机原理
  • 操作系统
  • 网络协议
  • 数据库原理
  • 面向对象
  • 设计原则
  • 设计模式
  • 系统架构
  • 性能优化
  • 编程原理
  • 方案设计
  • 稳定可靠
  • 工程运维
  • 基础认知
  • 线性结构
  • 树与哈希
  • 工业级实现
  • 算法思想
  • 实战与综合
  • 算法题考核
  • C语言入门
  • C综合案例
  • C专栏博客
  • C标准集库
  • C++入门教程
  • C++综合案例
  • C++专栏博客
  • C++开发技巧
  • Java入门教程
  • Java综合案例
  • Java专栏博客
  • Go入门教程
  • Go综合案例
  • Go专栏博客
  • Go开发技巧
  • JavaScript入门
  • JavaScript高级
  • Android库解读
  • Android专栏
  • Android智能硬件
  • iOS ObjC入门
  • iOS Swift入门
  • iOS入门精通
  • Web之Html手册
  • Web之TypeScript
  • Web之Vue高级进阶
  • Linux之QML入门
  • Linux之QT核心库
  • Linux实践开发
  • Python教程
  • Shell&Bash教程
  • 工具脚本
  • 自动化脚本
  • 质量保障
  • 产品思考
  • 软实力
  • 开发流程
  • Git应用
  • 技术模版
  • 技术规范
  • Markdown
  • Mermaid
  • 开源协议
  • JSON工具
  • 文本工具
  • 图片处理
  • 文档转化
  • 代码压缩
  • 关于我
  • 自我精进
  • 职场管理
  • 职场面试
  • 心情杂货
  • 友情链接
  • README
  • Android提升进阶

  • iOS开发和进阶

    • README
    • ObjC编程入门

      • README
      • ObjC基础语法
      • 面向对象编程
      • ObjC高级语法
      • ObjC内存管理
        • 4.1 生命周期设计
          • 4.1.1 初始化操作
          • 4.1.2 销毁时释放
        • 4.2 内存管理
          • 4.2.1 引用计数
          • 4.2.2 引用计数规则
          • 4.2.3 内存管理方式
        • 4.3 手动引用计数
          • 4.3.1 MRC案例
          • 4.3.2 MRC案例分析
          • 4.3.3 原理设计
          • 4.3.4 使用自动释放池
        • 4.4 自动引用计数
          • 4.4.1 ARC案例
          • 4.4.2 ARC案例分析
          • 4.4.3 原理设计
        • 4.5 内存最佳实践
          • 4.5.1 避免循环引用
          • 4.5.2 管理临时对象
          • 4.5.3 dealloc
          • 示例:
          • 4.5.4 MRC vs ARC
    • Swift编程入门

    • iOS入门到精通

  • Web开发和进阶

  • Linux应用开发

  • Apps
  • iOS开发和进阶
  • ObjC编程入门
杨充
2025-07-23
目录

ObjC内存管理

# 04.ObjC内存管理

# 目录介绍

  • 4.1 生命周期设计
    • 4.1.1 初始化操作
    • 4.1.2 销毁时释放
  • 4.2 内存管理
    • 4.2.1 引用计数
    • 4.2.2 引用计数规则
    • 4.2.3 内存管理方式
  • 4.3 手动引用计数
    • 4.3.1 MRC案例
    • 4.3.2 MRC案例分析
    • 4.3.3 原理设计
    • 4.3.4 使用自动释放池
  • 4.4 自动引用计数
    • 4.4.1 ARC案例
    • 4.4.2 ARC案例分析
    • 4.4.3 原理设计
  • 4.5 内存最佳实践
    • 4.5.1 避免循环引用
    • 4.5.2 管理临时对象
    • 4.5.3 dealloc
    • 4.5.4 MRC vs ARC

# 4.1 生命周期设计

对象的生命周期是指对象从创建到销毁的整个过程。了解对象的生命周期对于正确管理内存和资源以及避免潜在的问题非常重要。

# 4.1.1 初始化操作

1.分配(Allocation):在分配阶段,通过使用alloc和init方法或其他创建对象的方法,为对象分配内存空间,并初始化对象的实例变量。

MyObject *obj = [[MyObject alloc] init];
1
  • alloc:为对象分配内存。
  • init:初始化对象,设置默认值或执行其他初始化操作。

2.初始化(Initialization):在初始化阶段,可以在init方法中对对象的实例变量进行初始化,设置初始状态和执行其他必要的操作。

- (instancetype)init {
    self = [super init];
    if (self) {
        // 初始化实例变量
    }
    return self;
}

// 任何类在实例化之前都会先调用该方法
+ (void)initialize {  
    //这个比init方法先调用
}
1
2
3
4
5
6
7
8
9
10
11
12

# 4.1.2 销毁时释放

1.释放(Deallocation):在释放阶段,对象不再被使用,内存空间将被释放。当对象不再被引用时,Objective-C的自动引用计数(ARC)机制会自动处理对象的释放。

obj = nil; // 对象将被释放
1

2.释放前的清理(Cleanup before Deallocation):在对象被释放之前,可以在dealloc方法中执行一些清理操作,如释放资源、取消观察者、解除通知等。

// 对应于 initialize 方法,用于清空对象,当引用计数为 0 时被调用
- (void)dealloc {
    // 如果未启用 ARC,则需要手动释放引用计数
    [nickName release];
    // 清理操作
    [super dealloc];
}
1
2
3
4
5
6
7

# 4.2 内存管理

# 4.2.1 引用计数

引用计数是 Objective-C 内存管理的核心机制。每个对象都有一个引用计数器,用于记录当前有多少个对象在使用它。

# 4.2.2 引用计数规则

  • 当对象被创建时,引用计数为 1。
  • 当对象被其他对象引用时,引用计数加 1。
  • 当对象不再被引用时,引用计数减 1。
  • 当引用计数为 0 时,对象被销毁,内存被释放。

# 4.2.3 内存管理方式

内存管理是一项重要的任务,用于管理对象的生命周期和内存分配。在Objective-C中,有两种主要的内存管理方式:

手动引用计数(Manual Reference Counting,MRC)和自动引用计数(Automatic Reference Counting,ARC)。

# 4.3 手动引用计数

# 4.3.1 MRC案例

手动引用计数(MRC):在MRC中,开发者需要手动管理对象的引用计数,通过调用retain、release和autorelease等方法来增加或减少对象的引用计数。需要确保在不再使用对象时,适时地释放其内存。

MyObject *obj = [[MyObject alloc] init]; // 引用计数为1
[obj retain]; // 增加引用计数
//释放对象
[obj release]; // 减少引用计数
[obj autorelease]; // 在自动释放池中延迟释放
1
2
3
4
5

# 4.3.2 MRC案例分析

手动管理引用计数的方法

  • retain:增加对象的引用计数。
  • release:减少对象的引用计数。
  • autorelease:将对象添加到自动释放池,稍后释放。
  • dealloc:对象被销毁时调用的方法,用于释放资源。
// 创建对象,引用计数为 1
NSObject *obj = [[NSObject alloc] init];

// 增加引用计数
[obj retain]; // 引用计数为 2

// 减少引用计数
[obj release]; // 引用计数为 1

// 将对象添加到自动释放池
[obj autorelease]; // 引用计数为 1,稍后释放

// 手动释放对象
[obj release]; // 引用计数为 0,对象被销毁
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 4.3.3 原理设计

# 4.3.4 使用自动释放池

自动释放池用于延迟对象的释放。当对象被发送 autorelease 消息时,它会被添加到当前的自动释放池中。当自动释放池被释放时,池中的所有对象都会收到 release 消息。

@autoreleasepool {
    // 创建对象并添加到自动释放池
    NSString *str = [[[NSString alloc] initWithFormat:@"Hello, %@", @"World"] autorelease];

    // 使用对象
    NSLog(@"%@", str);

    // 自动释放池结束时,str 会被释放
}
1
2
3
4
5
6
7
8
9

# 4.4 自动引用计数

ARC 是 Objective-C 的编译器特性,它自动管理对象的引用计数,开发者无需手动调用 retain、release 和 autorelease。

# 4.4.1 ARC案例

自动引用计数(ARC):在ARC中,编译器会自动插入适当的引用计数管理代码,开发者无需手动管理对象的引用计数。编译器会根据代码的上下文自动添加retain、release和autorelease等操作。

MyObject *obj = [[MyObject alloc] init]; // 引用计数为1
obj = nil; // 引用计数 = 0,对象被销毁
// 不需要手动调用retain/release/autorelease
1
2
3

# 4.4.2 ARC案例分析

ARC 的规则

  • 编译器会自动在适当的位置插入 retain、release 和 autorelease。
  • 开发者不能手动调用 retain、release 和 autorelease。
  • 对象的生命周期由编译器管理。

# 4.4.3 原理设计

ARC:编译器自动插入 retain/release(默认模式)

属性修饰符:

  • strong:持有对象(默认)
  • weak:弱引用(自动置 nil)
  • copy:复制对象(用于 NSString/NSArray)
  • assign:基本数据类型(非对象)

1.强引用(Strong Reference):默认情况下,对象之间的引用是强引用,即强制保持对对象的引用,只有当所有强引用都被释放时,对象才会被释放。

// 默认值,变量会被保存在内存中直到离开作用域
__strong NSString *strongString;
1
2

2.弱引用(Weak Reference):使用__weak修饰符可以创建弱引用,弱引用不会增加对象的引用计数,当对象被释放时,弱引用会自动设置为nil。

// 弱引用,假如引用的对象被释放,那么弱引用会被设为 nil
__weak MyObject *weakObj = obj;

// 与弱引用类似,但是如果引用的对象被释放,引用也不会被设为 nil
__unsafe_unretained NSArray *unsafeArray;
1
2
3
4
5

3.循环引用(Retain Cycle):循环引用指的是两个或多个对象之间相互持有强引用,导致它们无法被释放。为了避免循环引用,可以使用__weak修饰符、__unsafe_unretained修饰符或使用弱引用的代理对象等方式。

__weak typeof(self) weakSelf = self;
1

4.手动释放内存:在MRC中,需要手动释放对象的内存,可以在适当的时机调用release方法。在ARC中,不需要手动释放内存,编译器会自动插入释放代码。

# 4.5 内存最佳实践

# 4.5.1 避免循环引用

循环引用会导致内存泄漏。使用 weak 引用或 __weak 修饰符来打破循环引用。

__weak typeof(self) weakSelf = self;
self.block = ^{
    [weakSelf doSomething]; // 使用 weakSelf 避免循环引用
};
1
2
3
4

# 4.5.2 管理临时对象

在循环中创建大量临时对象时,使用 @autoreleasepool 及时释放内存。

for (int i = 0; i < 1000; i++) {
    @autoreleasepool {
        NSString *tempStr = [NSString stringWithFormat:@"Temp %d", i];
        NSLog(@"%@", tempStr);
    }
}
1
2
3
4
5
6

# 4.5.3 dealloc

在 dealloc 方法中释放对象持有的资源。

# 示例:

- (void)dealloc {
    // 释放资源
    [_resource release];
    [super dealloc];
}
1
2
3
4
5

# 4.5.4 MRC vs ARC

手动内存管理与 ARC 的对比

特性 手动内存管理 ARC
引用计数管理 手动调用 retain、release 编译器自动管理
代码复杂度 较高,容易出错 较低,减少内存管理错误
性能 需要手动优化 编译器优化,性能较好
适用场景 需要精细控制内存的场合 大多数现代 Objective-C 项目
上次更新: 2026/06/10, 11:13:41
ObjC高级语法
README

← ObjC高级语法 README→

最近更新
01
信号崩溃快速排查
06-15
02
CoreDump破案
06-15
03
perf火焰图实战
06-15
更多文章>
Theme by Vdoing | Copyright © 2019-2026 杨充 | MIT License | 桂ICP备2024034950号 | 桂公网安备45142202000030
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式