Objective-C总结----5.内存管理

可执行程序构成

  • Objective-C可执行程序是由(可执行)代码、初始化和未初始化的程序数据、链接信息、重定位信息、局部数据和动态数据构成的。
    • 可执行程序、程序数据以及链接在重定位信息会以静态方式分配内存,并在程序的生命周期一直存在。
    • 局部数据在语句块中声明并且仅在该语句块中有效,当该语句块执行后局部数据不在继续存在,存在栈内存中,系统自动管理。
    • "动态数据"->Objective-C将创建的对象存储在动态分配的内存即“堆”内存中,我们需要进行唯一的内存管理。
  • 程序数据包包括以静态方式声明的变量和程序变量(即在程序编译时在代码中设置的常数)。

内存管理不当引起的问题

  • 内存泄漏
    如果程序没有释放不再使用的对象,就会导致内存泄漏,造成内存浪费,容易耗尽系统内存。
  • 悬挂指针
    如果程序释放了仍在使用的对象,就会导致该问题,为野指针或僵尸指针,向悬挂指针发送消息会导致程序奔溃。

Objective-C内存管理方式

Objective-C内存管理是通过引用计数实现的,引用计数是一种通过对象的唯一引用,确定对象是否正在被使用。如果对象的引用计数为零时,对象就被视为不再使用,系统将释放这个对象的内存。

苹果公司提供两种方式管理内存:

  • 手动管理MRR/MRC
  • 自动管理ARC->苹果推荐使用ARC,已经很成熟的计数

1.手动管理

手动管理是建立在“对象所有权”概念上的内存管理机制,只要对象的所有者还存在,对象就不会被Objective-C运行时环境释放。

  • 对象引用&对象所有权
    Objective-C对象是通过指向Objective-C对象内存地址的变量,以间接方式访问,这种变量也称为指针。
    如 KNZPerson *person = [[KNZPerson alloc]init];
    • person为一个指针变量,保存着对象的内存地址
    • [[KNZPerson alloc]init]为创建一个对象并初始化,返回对象的地址</br>

再创建一个指针变量person2,将person赋值给person2,那么person2拥有指向该对象的内存地址。

 -  KNZPerson *person2  = person;

如果person2没有获得该对象的所有权(通过赋值语句无法获得所有权)的话,当person被释放(person不再指向该对象,该对象被释放),那么person2保存的对象地址指向的内存空间不再存在,person2就是悬挂指针,因此我们需要以手动的方式管理对象的生命周期(保留和释放),在编写代码时***(面向类Class设计时添加内存管理代码)***必须遵守一些内存管理规则。
  • 手动内存管理规则
    • 为创建的所有对象设置所有权
      • 创建:alloc、new、copy或者mutableCopy,计数器+1

      注意:Foundation里面的类用alloc创建时也需要进行内存管理,但是使用一些便利方法创建的不需要:
      例如:NSString *str = [[NSString alloc]initWithFormat:@"A1"];
      需要[str release];
      NSString *str2 = [NSString stringWithFarmat:@"A2"];
      不需要进行内存管理
      - 应使用retain方法获取对象的所有权
      - retain:计数器+1
      - 当不再使用某个对象时,必须放弃其所有权
      - release:计数器-1
      - 当计数器=0对象自动释放,释放时自动调用dealloc方法
      - 不能放弃不归你所有的对象所有权

例如:
KNZPerson *person = [[KNZPerson alloc]init];
alloc创建一个对象并且赋予person,计数器+1,当前值为1;
KNZPerson *person2 = [person retain];
person指向的对象发送消息retain,计数器+1,当前值为2;
当person不再指向该对象的话[person release];
计数器-1,当前值为1;
还有指针变量person2指向该对象,该对象不会被释放;
[person2 release];person2也不再指向该对象,计数器-1,当前值为0,
系统认为该对象不再被使用,系统自动调用dealloc方法释放掉该对象。

MRR管理内存情况下如何设计一个类
  • 设计一个类拥有其他对象时,初始化时被创建的其他对象引用计数器+1(记得在对象释放调用dealloc方法中,释放掉这些其他对象)
  • 创建这个类的实例对象时,这个对象的引用计数器自动+1,就可以拥有这个对象了,不用管对象内部所拥有的其他对象。
  • 当这个对象的引用计数器=0时,系统自动调用对象的dealloc方法释放此对象,当对象拥有其他对象时,需要在dealloc方法里面释放掉所拥有的对象,最后调用[super dealloc]方法,彻底释放对象。
@autorelease{自动释放代码块}
  • 在自动释放池里面创建一个实例对象并对这个对象发送autorelease消息,无需再对对象进行内存管理,对象会在释放池最后释放掉。
    如 KNZPerson *person = [[[KNZPerson alloc]init]autorelease];

  • 用于创建iOS和macOS应用的苹果UI框架、尤其是AppKit和UIKit,能够自动提供自动释放代码块。

  • 需要在自动释放池中手动编写自动释放代码块:

    • 你编写的程序不是以苹果UI框架为基础的,如命令行工具
    • 你实现的逻辑中含有创建许多临时对象的循环。
    • 你编写的应用派生了一个或多个辅助线程。

自动管理ARC

自动引用计数是一种功能强大的内存管理工具。与MRR相同,也是通过对象引用计数器来管理对象保留及释放,编译程序时由编译器分析源代码,在编译代码必要位置自动插入retain和release消息。
苹果公司推荐使用ARC进行内存管理。

ARC使用规则和约定

  • 不能手动编写发送retain、retainCount、release、autorelease、dealloc消息
  • 不能直接进行id和(void *)类型的互换
  • 需要使用自动释放池代码块执行由ARC管理的自动释放操作
  • 不能使用C结构体重的对象指针。
  • 不能使用内存去NSZone
  • 为了与非ARC代码协作,不能创建以“copy”开头的方法和自动声明属性
  • 默认情况下,ARC并非异常安全。

ARC的生命周期限定符

用来声明常规变量和属性的生命周期

  • 常规变量生命周期
    • _strong,默认配置
    • _weak,表面对象随时被释放,当对象被释放,指针变量会被设置为nil
    • _unsafe_unretained,与_weak类似,但指针变量不会设置为nil而是悬挂
    • _autorelease,与autorelease方法无关,用于通过引用传递对象。
  • 属性生命周期
    • strong,默认配置,等同于retain
    • weak,类似于assign特性,如果引用对象被释放了,其实例变量会被设置为nil。

循环引用解决方法weak

  • 设计类时,类A拥有类B的实例变量,类A强stong指向类B的实例变量;当类B也拥有类A的实例变量,这个时候用类B也用strong指向类A的实例变量话,那么就无法释放A和B的实例对象了,这个时候需要有一方weak弱指向对方,当对象A释放后,对象B弱weak指向对象A,对象B指针被设置为nil,对象B也会被释放的。

  • 一般iOS开发界面UI控件都用weak,因为添加到window的控件都会被Window强引用着,没有必要再使用一个指针强引用着UI控件。

  • delegate属性一般weak特性,因为带有代理设计的tableview或者textField之类的UIView控件都会让控制器成为它的代理,控制器已经有强指针指着UIView根视图,根视图再指向带有代理设计的tableview或者textField之类的UIView控件,这个时候使用delegate再strong指向控制器的话就会造成循环引用。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,026评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,655评论 1 296
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,726评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,204评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,558评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,731评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,944评论 2 314
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,698评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,438评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,633评论 2 247
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,125评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,444评论 3 255
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,137评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,103评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,888评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,772评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,669评论 2 271

推荐阅读更多精彩内容