黑马程序员——OC基础—内存管理

------- android培训、ios培训、期待与您交流! ----------

=== 内存管理机制 ===

OC的局部变量在代码块结束时被系统销毁, 内存被回收.

OC的对象, 内部有引用计数器, 当引用计数器的值为0时, 被系统销毁, 内存被回收.

 

局部变量存放在栈中. 对象存放在堆中.

注意, 对象指针还是存放在栈中, 对象本身占用的内存存放在堆中.

 

在OC中, 我们要对自己写的继承了NSObject的对象进行内存管理.

 

对象在建立(alloc, new, copy)时, 引用计数器的值为1.

对象调用retain方法, 引用计数器的值+1.

对象调用release方法, 引用计数器的值-1.

使用retainCount返回引用计数器的值. (unsigned long)

当对象的引用计数器的值为0时, 对象就会被系统销毁, 内存被回收.

 

对象被销毁时, 系统会调用对象的dealloc方法. 重写dealloc方法释放相关资源, 证实对象被回收. dealloc方法最后要调用[super dealloc];

 

野指针: 在对象被销毁后, 把指针设为nil. 使用野指针调用方法, 会发生错误.

 

=== 对象的内存管理 ===

[main函数中]

每使用alloc, new, copy一次, 就release一次. 并设空指针.

每使用retain一次, 就release一次.

 

注意: NSString *对象不是alloc产生的, 所以不用release.

 

当给这个对象设置对象属性时, 要给属性对象的计数器+1.

当这个对象切换对象属性时, 要给原有的属性对象计数器-1, 给新的属性对象计数器+1. 但是要注意新对象和原对象是否是同一个对象.

当这个对象被释放时, 要给它的所有属性对象的计数器-1.

 

set方法的写法注意:

1 要release原来的属性对象

2 要retain新加的属性对象

3 要判断要替换的属性对象和现有的是否是同一个对象, 如果是, 就不要release

 

dealloc方法的重写:

1 释放所有的对象类型的属性

2 调用[super dealloc];

3 打印内容, 方便查看是不是所有创建的对象都被释放.

 

#  使用 @property 的参数生成恰当的set方法  

@property的参数:

assign, retain, copy

nonatomic, atomic

readonly, readwrite

setter = setName:, getter = getName

  

基本数据类型的属性, 使用assign参数

OC对象的属性, 使用retain参数

字符串类型的属性, 通常使用copy参数

 

使用retain, 编译器会根据@property生成上面那种三行管理内存的setter方法.

使用assign, 编译器会根据@property生成一行直接赋值的setter方法. 

使用copy, 编译器会生成使用copy的setter方法, 使得属性是原字符串的拷贝.

 

因为如果双方在声明中都互相#import, 会造成循环引用.

以后只要一个类包含的属性是另一个类, 在类的声明中使用@class, 在实现中使用#import

@class 类名

这样就声明类,但是如果需要用到该类中的成员变量或者方法,则还需要使用#import

 

# 释放池

对小内存的对象, 可以使用 @autorelease 代替 release. 使用@autorelease的对象在释放池被销毁时被release一次.

可以在类中提供类方法直接创建autorelease的对象, 注意在新建对象时, 使用 [self alloc] 而不是 [类名 alloc] 以方便子类调用时能够返回子类的对象. 这样的类方法通常以类名开头. 系统自带的这类方法也是带有autorelease的.

[[[类名 alloc] init] autorelease];

上述代码在释放池中,可以不用在最后调用对象的release方法。它会在释放池结束的时候自动让计数器-1.

=== 内存管理知识点总结 ===

1 在main函数中

        1> 有alloc就要release

        2> 有retain 就release

2 对象类型的属性的set方法的三要素:

        1> 判断是否是同一对象

        2> release原来的对象

        3> retain新设的对象, 并设置为属性

        4> 注意: 如果两个类互为对方的属性, 一边使用retain, 另一边直接赋值(assign).

3 重写dealloc方法:

        1> 释放所有在set方法中retain过的属性

        2> 可以打印内容, 方便检查是否所有新建的对象都在程序结束前被释放

        3> 要调用[super release];

4 原则

        1> 谁alloc, 谁release

        2> 谁retain, 谁release

        3> 不是自己alloc的就不需要release, 比如很多静态方法创建的对象就不需要release

5 在类的声明中使用@class, 在类的实现中使用#import, 提高效率, 并避免互相循环#import

=== ARC 的使用 === 

ARC是编译器特性, 默认指向对象的指针都是强指针, 使用__weak标记的是弱指针. 如果没有强指针指向对象了,这个对象就会被销毁 (编译器会自动添加 retain, release代码). 如果对象被销毁了, 指向它弱指针会被自动清空, 以防野指针错误.

ARC的使用:

        1. 即使有alloc也不需要写release或autorelease, 不允许使用retain.

        2. set方法对对象类型的属性使用strong代替retain

        2. 不需要在dealloc方法中释放属性

也就是说, 有了ARC就不需要关注内存管理了, 怎么写都不会错.

你可能感兴趣的:(OC学习交流)