黑马程序员————oc内存管理

------ Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

1,为什么管理内存

1)移动设备的内存极其有限,每个app所能占用的内存是有限制的
2)当app所占用的内存较多时,系统会发出内存警告,这时得回收一些不需要再使用的内存空间。比如回收一些不需要使用的对象、变量等
3)管理范围:任何继承了NSObject的对象,对其他基本数据类型(int、char、float、double、struct、enum等)无效

2,引用计数器

1)对象的基本结构
(1)每个OC对象都有自己的引用计数器,是一个整数,表示“对象被引用的次数”,即有多少人正在使用这个OC对象。
(2)每个OC对象内部专门有4个字节的存储空间来存储引用计数器。

2)引用计数器的作用
当一个对象的引用计数器值为0时,对象占用的内存就会被系统回收。换句话说,如果对象的计数器不为0,那么在整个程序运行过程,它占用的内存就不可能被回收,除非整个程序已经退出。

3)引用计数器的操作
(1)alloc, allocWithZone,new(带初始化)为对象分配内存,retainCount为“1”,返回此实例。
(2)retain,retainCount 加“1”。
(3)copy,mutableCopy复制一个实例,retainCount数为“1”,返回此实例。
(4)releas,eretainCount 减“1”,减到“0”时调用此对象的dealloc方法
(5)retainCount,获得当前的引用计数器值。

4)对象的销毁
(1)当一个对象的引用计数器值为0时,那么它将被销毁,其占用的内存被系统回收
(2)当一个对象被销毁时,系统会自动向对象发送一条dealloc消息
(2)一般会重写dealloc方法,在这里释放相关资源,dealloc就像对象的遗言
(3)一旦重写了dealloc方法,就必须调用[super dealloc],并且放在最后面调用
(4)不要直接调用dealloc方法
(5)一旦对象被回收了,它占用的内存就不再可用,坚持使用会导致程序崩溃(野指针错误)

3,内存管理原则

1)谁创建,谁release。如果你通过alloc、new或[mutable]copy来创建一个对象,那么你必须调用release或autorelease。
2)谁retain,谁release。只要你调用了retain,无论这个对象是如何生成的,你都要调用release。
3)一般来说,除了alloc、new或copy之外的方法创建的对象都被声明了autorelease

4,set方法的内存管理

如果你有个OC对象类型的成员变量,就必须管理这个成员变量的内存。
1)set方法的实现举例:
- (void)setStu:(Stu *)stu
{
	if (stu != _stu) {
		[_stu release];
		_stu = [stu retain];
	}
}
2)dealloc方法的实现
- (void)dealloc {
	[_stu release];
	[super dealloc];
}

5,@property参数

1)控制set方法的内存管理
(1)retain : release旧值,retain新值(用于OC对象)
(2)assign : 直接赋值,不做任何内存管理(默认,用于非OC对象类型)
(3)copy   : release旧值,copy新值(一般用于NSString *)

2)控制需不需生成set方法
(1)readwrite :同时生成set方法和get方法(默认)
(2)readonly  :只会生成get方法

3)多线程管理
(1)atomic    :性能低(默认)
(2)nonatomic :性能高

4)控制set方法和get方法的名称
(1)setter : 设置set方法的名称,一定有个冒号:
(2)getter : 设置get方法的名称

6,autorelease

1)autorelease
给某个对象发送一条autorelease消息时,就会将这个对象加到一个自动释放池中
当自动释放池销毁时,会给池子里面的所有对象发送一条release消息
调用autorelease方法时并不会改变对象的计数器,并且会返回对象本身
autorelease实际上只是把对release的调用延迟了,对于每一次autorelease,系统只是把该对象放入了当前的autorelease  pool中,当该pool被释放时,该pool中的所有对象会被调用Release

2)创建自动释放池
ios 5.0后
@autoreleasepool
{
    // ....
}

3)autorelease的基本用法
(1)将对象放到一个自动释放池中
(2)当自动释放池被销毁时,会对池子里面的所有对象做一次release操作
(3)会返回对象本身
(4)调用完autorelease方法后,对象的计数器不变。
(5)一般来说,除了alloc、new或copy之外的方法创建的对象都被声明了autorelease

4)错误写法 
(1)alloc之后调用了autorelease,又调用release
 @autoreleasepool
 {
    // 1
    Person *p = [[[Person alloc] init] autorelease];
    // 0
    [p release];
 }

(2)连续调用多次autorelease
 @autoreleasepool
 {
    Person *p = [[[[Person alloc] init] autorelease] autorelease];
 }

5)autoreleasepool举例
int main(int argc , const char *crgv[])
{
  @autoreleasepool
	{ 
        Stu *stu1 = [[[Stu alloc] init] autorelease];
        stu1.age = 21;
        @autoreleasepool
        { 
			Stu *stu2 = [[[Stu alloc] init] autorelease];
            stu2.age = 22;   
        }
        Stu *stu3 = [[[Stu alloc] init] autorelease];
    } 
}

7,ARC

1)基本简介
(1)ARC是自iOS5之后增加的新特性,完全消除了手动管理内存的烦琐,编译器会自动在适当的地方插入适当的retain、release、autorelease语句。你不再需要担心内存管理,因为编译器为你处理了一切。
(2)ARC是编译器特性,而不是iOS运行时特性,它也不是类似于其它语言中的垃圾收集器。因此ARC和手动内存管理性能是一样的,有时还能更加快速,因为编译器还可以执行某些优化。

2)基本原理
(1)规则:ARC 的规则非常简单:只要还有一个强指针变量指向对象,对象就会保持在内存中。
(2)强指针和弱指针:默认所有实例变量和局部变量都是Strong指针。弱指针指向的对象被回收后,弱指针会自动变为nil指针,不会引发野指针错误。

3)使用注意
(1)不能调用release、retain、autorelease、retainCount。
(2)可以重写dealloc,但是不能调用[super dealloc]。
(3)@property : 想长期拥有某个对象,应该用strong,其他对象用weak。
(4)其他基本数据类型依然用assign。
(5)两端互相引用时,一端用strong、一端用weak。

你可能感兴趣的:(IOS学习笔记)