1、内存管理的方式

 1> iOS应用程序出现Crash(闪退),90%的原因是因为内存问题。

 2> 内存问题

  • 野指针异常:访问没有所有权的内存,如果想要安全的访问,必须确保空间还在
  • 内存泄露:空间使用完之后没有及时释放
  • 过度释放:对同一块存储空间释放多次,立刻crash
  • 内存溢出:所有存储空间被占用

 3> 管理内存的三种方式

  垃圾回收机制:程序员只需要开辟存储空间,系统会自动回收内存。java采用的该机制

  MRC:手动引用计数机制,由开发人员开辟空间,手动添加影响引用计数增加或减少的方法,能够灵活的控制空间何时释放

  ARC:自动引用计数机制,是iOS5.0推出的,基于MRC,不需要程序员手动添加管理内存的代码,编译器会在合适的地方自动添加管理内存的代码

  MRC和ARC都是采用引用计数来管理对象内存

 4> iOS的内存管理

  iOS支持两种内存管理方式:ARC和MRC。

  MRC的内存管理机制是:引用计数。

  ARC是基于MRC的。

2、引用计数机制

 1> 引用计数

  OC采用引用计数机制管理内存,每个对象都有一个引用计数器,用来记录当前对象的引用次数。

  iOS采用引用计数来管理内存,当你想拥有这个对象的时候,需要使该对象的引用计数+1,使用完这个对象的时候,使该对象的引用计数-1,当对象的引用计数为时,表示没有任何对象对该对象持有,那么这时候系统会自动调用dealloc方法来回收该对象的存储空间。

 2> 影响引用计数的方法

  retainCount 获取对象的引用计数。(retainCount它是MRC才有的机制,所以如果使用需要将ARC改为MRC)。

  ARC改为MRC:点击过程名 ---> Build Setting ---> 将Objective - C Automatic Counting 由YES改为NO

  

  ① 使计数器加1的方法:alloc,retain,copy。

   +alloc 开辟内存空间,让被开辟的内存空间的引用计数从变为.

-retain 引用计数加1,如果对象之前引用计数为,retain之后变为,如果引用计数是5,retain之后变为6。

-copy 把某一对象的内容拷贝一份,拷贝出新的对象,原有对象的引用计数不变,新的对象的引用计数变1。

  ② 使计数器减1的方法:release,autorelease。

-release 引用计数立即减1,如果对象之前的引用计数为4,release之后变为3,如果之前引用计数是1,release之后变为0,内存被系统回收。

-autorelease 未来的某一时刻引用计数减1,如果对象之前引用计数为4,autorelease之后仍然为4,未来某个时刻会变为3,这个某一时刻指的是碰到自动释放池之后才会释放。

 3> autoreleasepool的使用

  通过autoreleasepool自动释放池,控制autorelease对象的释放。向一个对象发送autorelease消息,该对象就会添加到离autorelease最近的自动释放池中,当自动释放池销毁时,为池中的每一个对象发送release消息。

  定义一个自动释放池

  第一种方式

         // 第一种形式
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // pool 1
NSLog(@"pool = %lu", pool.retainCount); Person *p1 = [[Person alloc] init];
NSLog(@"p1 = %lu", p1.retainCount); [p1 retain]; // [p1 autorelease]; // 未来的某一时刻-1
NSLog(@"p1 = %lu", p1.retainCount); // [pool release]; // 销毁自动释放池
NSLog(@"p1 = %lu", p1.retainCount); //

  第二种方式

        // 在iOS5.0之后推荐使用
@autoreleasepool {
Person *p5 = [[Person alloc] init];
[p5 autorelease];
}

  总结:自动释放池的作用:自动释放池会在销毁之前检查内部有没有autorelease对象,如果有autorelease对象,让该对象的引用计数做一次-1操作

 4> dealloc

  -dealloc 是继承自父类的方法,当对象引用计数为0的时候,由对象自动调用,销毁该对象的空间。

  重写 dealloc 方法,验证对象的空间是否被回收。

  - (void)dealloc {
NSLog(@"%@对象被销毁", self);
[super dealloc]; // 类对该方法的实现才是真正的回收空间
}

3、内存管理原则

  凡是使用alloc,retain让对象的引用计数+1,相应的就该使用release或者autorelease让对象的引用计数-1,也就是说增加的次数要和减少的次数相等,才能保证对象的引用计数最终为0,对象才会被销毁。

 1> 内存泄露:增加的次数大于减少的次数

         Person *person2 = [[Person alloc] init]; //
[person2 retain]; //
[person2 release]; //

 2> 过度释放:增加的次数小于减少的次数

         Person *person1 = [[Person alloc] init];
[person1 retain];
[person1 release];
[person1 release];
[person1 release]; // 过度释放

 3> 野指针异常:增加的次数等于减少的次数,还将继续访问

         Person *person = [[Person alloc] init];
[person retain];
[person release];
[person release];
person = nil; // 对象置为nil, 防止野指针异常
NSLog(@"person = %lu", person.retainCount);

4、协议

 1> 概述  

  Protocol(协议),是iOS开发中常用的技术。
  协议是一套标准(一堆方法的声明),只有.h文件。就像一张任务清单(或便利贴),上面写了一堆需要处理的事。清单交给谁,谁就要去完成清单上规定的任务。
  接受协议的类实现协议中定义的方法。即:清单交给谁,谁就要去完成清单上规定的任务。

 2> 协议的定义

  协议的定义:command + n —> 选择OS X下的 source —> Objective-C File —> Next —> 弹出下图。

 3> 协议的方法

  协议中的方法默认是必须实现的,即@required。关键字@optional修饰的方法是可选的,可实现也可不实现。

         #import <Foundation/Foundation.h>
@protocol SayHello <NSObject>
// 协议中的方法有两种,一种必须实现的,另一种是可选择实现的。
//必须实现的方法,默认方法就是必须实现的。
@required
- (void)sayHello;
//可选择实现的方法。
@optional
- (void)sayByeBye;
@end

 4> 协议的使用

  在类的.h文件中,在当前类父类的后面使用一对尖括号<>,遵循协议一个类可以遵循多个协议,每个协议用逗号隔开。

     @interface Person : NSObject<MarryProtocol,NSCopying>

5、拷贝                                       

 1> copy概述

  跟retain不同,一个对象想要copy,生成自己的副本,需要服从NSCopying协议,定义copy的细节(如何copy)。如果类没有接受NSCopying协议而给对象发送copy消息,会引起crash。

 2> NSCopying协议中的方法

  选中NSCopying,按住Command + 鼠标左键,进入协议查看协议中方法

@protocol NSCopying

- (id)copyWithZone:(nullable NSZone *)zone;

@end

 3> 根据copyWithZone:方法的实现不同,拷贝分为三种类型

  • 伪拷贝 : 拷贝地址,相当于retain,引用计数+1

  copyWithZone: 方法的实现

 - (id)copyWithZone:(NSZone *)zone {

     // 伪拷贝 : 拷贝地址,相当于retain,引用计数+1
return [self retain]; }
  • 浅拷贝:对象开辟新的空间,但两个对象的实例变量指向同一块存储空间

  copyWithZone: 方法的实现

 - (id)copyWithZone:(NSZone *)zone {

     // 浅拷贝:对象开辟新的空间,但两个对象的实例变量指向同一块存储空间

     Person *person = [[Person allocWithZone:zone] init];
person.name = self.name;
person.gender = self.gender; return person;
}
  • 深拷贝:对象开辟新的存储空间,并且两个对象的实例变量指向不同的存储空间

  copyWithZone: 方法的实现

 - (id)copyWithZone:(NSZone *)zone {

     // 深拷贝:对象开辟新的存储空间,并且两个对象的实例变量指向不同的存储空间
Person *person = [[Person allocWithZone:zone] init];
person.name = [self.name mutableCopy];
person.gender = [self.gender mutableCopy];
return person; }

4> 浅拷贝与深拷贝的区别(面试题)

  如果是深拷贝,那么成员对象的地址和之前的地址不同,如果是浅拷贝,成员变量的地址和之前的地址相同。

iOS学习17之OC内存管理的更多相关文章

  1. 【原】iOS学习18之OC内存管理高级

    1.属性的内存管理 1> 属性的语义特性 2> assign下的属性内部实现 @property (nonatomic, assign) NSString *name; @synthesi ...

  2. iOS学习笔记之ARC内存管理

    iOS学习笔记之ARC内存管理 写在前面 ARC(Automatic Reference Counting),自动引用计数,是iOS中采用的一种内存管理方式. 指针变量与对象所有权 指针变量暗含了对其 ...

  3. iOS学习之Object-C语言内存管理

    一.内存管理的方式      1.iOS应用程序出现Crash(闪退),90%的原因是因为内存问题.      2.内存问题:      1)野指针异常:访问没有所有权的内存,如果想要安全的访问,必须 ...

  4. iOS学习之Object-C语言内存管理高级

    一.属性的内存管理

  5. iOS学习之C语言内存管理

         一.存储区划分      按照地址从高到低的顺序:栈区,堆区,静态区,常量区,代码区    1.栈区:局部变量的存储区域     局部变量基本都在函数.循环.分支中定义     栈区的内存空 ...

  6. iOS经典面试题总结--内存管理

    iOS经典面试题总结--内存管理 内存管理 1.什么是ARC? ARC是automatic reference counting自动引用计数,在程序编译时自动加入retain/release.在对象被 ...

  7. OC 内存管理机制总结

    OC 内存管理机制总结 一:OC内存管理机制目前分为两块,其一自动内存管理机制,其二手动内存管理机制: 1.首先我们从自动内存管理机制讲起: 1)什么是自动内存管理机制,自动内存管理机制就是程序中所创 ...

  8. OC内存管理-OC笔记

    内存管理细节:http://blog.sina.com.cn/s/blog_814ecfa90102vus2.html 学习目标 1.[理解]内存管理 2.[掌握]第一个MRC程序 3.[掌握]内存管 ...

  9. OC内存管理总结,清晰明了!

    <span style="font-size:18px;">OC内存管理 一.基本原理 (一)为什么要进行内存管理. 由于移动设备的内存极其有限.所以每一个APP所占的 ...

随机推荐

  1. adb device 调试

    1. kill掉占用adb端口的进程 netstat -aon|findstr "5037" TCP 127.0.0.1:5037 0.0.0.0:0 LISTENING 6540 ...

  2. 瞧一瞧迷一般的SQLDA

    With static SQL, host variables used in embedded SQL statements are known at application compile tim ...

  3. Foreign key (referential) constraints on DB2 LUW v105

    oreign key constraints (also known as referential constraints or referential integrity constraints) ...

  4. iOS源码之OC相册,可以循环查看图片

    #import "ViewController.h" #import "YZUIScrollView.h" #define kuan ([UIScreen ma ...

  5. DOM - EventListener 句柄操作

          <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" c ...

  6. 关于Mesos和Kubernetes的区别

    这个主题应该和服务发现注册一样,进入视野...

  7. 【131202】SQL

    SELECT TOP 2 * FROM Persons SELECT *FROM PersonsWHERE ROWNUM <= 5   SELECT * FROM Persons WHERE C ...

  8. jQuery发送ajax请求

    利用jquery发送ajax请求的几个模板代码. $.ajax({ async : false, type: 'POST', dataType : "json", url: &qu ...

  9. android 入门-android Studio 解决方案

    一.当提示 解决方案: 1. 2. 二.从这步到这步 的时候,可能遇见下面的问题. 解决方案: 更新一下build-tools 19.1.0版本 放到你的sdk里并重启as. 三. 当遇见这样的情况 ...

  10. jquery获取radio和select选中值

    //jquery 获取radio选中值 <input type="radio" name="c_type" value="a" > ...