码迷,mamicode.com
首页 > 其他好文 > 详细

[黑马程序员]Objective-C 内存管理

时间:2015-04-20 16:30:08      阅读:126      评论:0      收藏:0      [点我收藏+]

标签:

引用计数器

每个OC对象都有自己的引用计数器,是一个整数表示对象被引用的次数,即现在有多少东西在使用这个对象。对象刚被创建时,默认计数器值为1,当计数器的值变为0时,则对象销毁。

在每个OC对象内部,都专门有4个字节的存储空间来存储引用计数器。

作用:

判断对象要不要回收的唯一依据就是计数器是否为0,若不为0则存在。

操作:

给对象发送消息,进行相应的计数器操作。

  • Retain消息:使计数器+1,该方法返回对象本身
  • Release消息:使计数器-1(并不代表释放对象)
  • retainCount消息:获得对象当前的引用计数器值

对象的销毁:

当一个对象的引用计数器为0时,那么它将被销毁,其占用的内存被系统回收。

当对象被销毁时,系统会自动向对象发送一条dealloc消息,一般会重写dealloc方法,在这里释放相关的资源,dealloc就像是对象的“临终遗言”。一旦重写了dealloc方法就必须调用[super dealloc],并且放在代码块的最后调用(不能直接调用dealloc方法)。

Person.m:

#import <Person.h>

@implementation Person

- (void) dealloc{
    NSLog(@"Person dealloc...");
    [super dealloc];
}

@end

main.m

#import <Person.h>

int main(){
    // 当我们调用alloc之后,p的引用计数器+1
    Person *p = [[Person alloc] init];
    // 手动调用release方法来对计数器-1,当检测到计数器为0时,就会调用dealloc方法销毁对象
    [p release];
    
    return 0;
}

相关概念

野指针:

指针指向一个已经被回收的地址。

如上例中,在指向完[p release]之后,p就作为一个野指针存在。

空指针:

没有指向任何东西的指针(存储的东西是0,null,nil),给空指针发送消息不会报错。

如上例中,我们将[p release]改成 p = nil p即为空指针。

原则

1、准则:

  • 只要还有人在使用某个对象,那么这个对象就不会被回收
  • 只要你想使用这个对象,那么就应该让这个对象的引用计数器+1
  • 当你不想使用这个对象时,应该让对象的引用计数器-1

2、谁创建,谁release

如果你通过alloc,new,copy来创建了一个对象,那么你就必须调用release或者autorelease方法。

3、谁retain,谁release

只要你调用了retain,无论这个对象时如何生成的,你都要调用release

4、总结

有始有终,有加就应该有减。曾经让某个对象计数器加1,就应该让其在最后-1。

代码规范

1、只要调用了alloc,就必须有release(autorelease)

2、Set方法的代码规范

(1) 基本数据类型

- (void) setAge: (int) age{
    _age = age;
}

(2) OC对象类型

- (void) setCar: (Car *) car{
    // 判断新设置的对象是否是成员变量里保存的对象
    if(car != _car){
        // 对旧对象进行release
        [_car release];
        // 对新对象进行retain并赋值给成员变量(retain方法返回对象本身)
        _car = [car retain];
    }
}

3、dealloc方法

  • 一定要[super dealloc],而且要放到最后
  • 对self(当前)所拥有的的其他对象做一次release操作

Autorelease

Person *p = [[[Person alloc] init] autorelease];

基本:

  • 会将对象放到一个自动释放池中
  • 当自动释放池被销毁时,会对池子里的所有对象做一次release
  • 会返回对象本身
  • 调用完autorelease方法后,对象的计数器不受影响(销毁时影响)

好处:

  • 不需要再关心对象释放的时间
  • 不需要再关心什么时候调用release

注意:

  • 连续调用多次autorelease,释放池销毁时执行两次release
Person *p = [[[[Person alloc] init] autorelease] autorelease];
  • alloc之后调用了autorelease,之后又调用了release。
Person *p = [[[Person alloc] init] autorelease];
[p release];

自动释放池:

  • 在ios程序运行过程中,会创建无数个池子,这些池子都是以栈结构(先进后出)存在的
  • 当一个对象调用autorelease时,会将这个对象放到位于栈顶的释放池中

自动释放池的创建方式:

  • iOS 5.0以前的创建方式
NSAutoreleasePool *pool=[[NSAutoreleasePool alloc] init];

// ...逻辑代码

[pool  release]; // 在mac中,使用[pool drain]
  • iOS 5.0以后
@autoreleasepool{

    // ...逻辑代码

}

ARC内存管理机制

ARC是Automatic Reference Counting---自动引用计数。

有自动引用计数,那么就得有手动引用计数MRC(Mannul Reference Counting),前面已经提到的就是MRC。

指针类型:

指针分为强指针和弱指针

// 强指针
Person *p = [[[Person alloc] init] autorelease];
// 强指针
__strong Person *p = [[[Person alloc] init] autorelease];
// 弱指针
__weak Person *p = [[[Person alloc] init] autorelease];

也就是说,通过__strong和__week来区分强指针和弱指针,默认情况下,所有指针都是强指针,前面有个__strong

特点:

  • 不允许调用release,retain,retainCount等内存管理方法
  • 允许重写dealloc, 但是不允许调用[super dealloc]
  • 当没有强指针指向这个对象时,这个对象就会被回收

[黑马程序员]Objective-C 内存管理

标签:

原文地址:http://www.cnblogs.com/imabel/p/4441578.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!