黑马程序员——08-内存管理之二

一、autorelease

1、自动释放池

1) 在iOS程序运行过程中,会创建多个自动释放池。这些池子都是以栈结构存在(栈的特点先进后出)

2) 当一个对象调用autorelease方法时,会将这个对象放到栈顶的释放池

2autorelease的基本用法

1)在给某个对象发送一条autorelease消息时,会将对象放到一个自动释放池中

2) 当自动释放池被销毁时,会对池子里面的所有对象做一次release操作,并返回对象本身

3)调用完autorelease方法后,对象的计数器不变

3、自动释放池的创建方式

 (1) iOS 5.0

 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // 开始
 
 [pool release]; // 结束

结束句还可以写作[pool drain];

2iOS 5.0 开始

@autoreleasepool
 { // 以{ 开始,代表创建了释放池
    
 } // 以} 结束,代表销毁释放池

3)创建多个自动释放池

示例:

@autoreleasepool
{
    Person *p = [[[Person alloc] init] autorelease];
    p.age = 10;
    @autoreleasepool
    {
<span style="white-space:pre">	</span>Person *p2 = [[[Person alloc] init] autorelease];
<span style="white-space:pre">	</span>p2.age = 10;
    }
    Person *p3 = [[[Person alloc] init] autorelease]; 
}

autorelease实际上只是把对release的调用延迟了,对于每一次autorelease,系统只是把该对象放入了当前的autorelease pool中,当该pool被释放时,该pool中的所有对象会被调 用Release


4autorelease的好处

1)不用再关心对象释放的时间

2)不用再关心什么时候调用release


 5autorelease的使用注意

1)占用内存较大的对象不要随便使用autorelease

2)占用内存较小的对象使用autorelease,没有太大影响

 

 6、错误写法

1alloc之后调用了autorelease,又调用release

示例:

@autoreleasepool
 {
    Person *p = [[[Person alloc] init] autorelease];
    [p release];
 }

2)连续调用多次autorelease

@autoreleasepool
 {
    Person *p = [[[[Person alloc] init] autorelease] autorelease];
 }

7、补充

1.系统自带的方法里面没有包含allocnewcopy,说明返回的对象都是autorelease

2.开发中经常会提供一些类方法,快速创建一个已经autorelease过的对象

1) 创建对象时不要直接用类名,一般用self

 + (id)person
 {
    return [[[self alloc] init] autorelease];
 }

2)一般可以为类添加一个快速创建对象的类方法

+ (id)book
{
    return [[[Bookalloc] init] autorelease];
}


外界调用[Bookbook]时,根本不用考虑在什么时候释放返回的Book对象


二、ARC

1ARC简介

1ARCAutomatic Reference Counting(自动引用计数)的简称,iOS 5之后增加的新特性,完全消除了手动管理内存的烦琐,编译器会自动在适当的地方插入适当的retainreleaseautorelease语句,不再需要担心内存管理问题。

2ARC 是编译器特性,而不是 iOS 运行时特性,它也不是类似于其它语言中的垃圾收集器。因此 ARC 和手动内存管理性能是一样的,有时还能更加快速,因为编译器还可以执行某些优化

 

2ARC的判断准则

1)规则:只要没有强指针指向对象,就会释放对象

2)指针分类

a) 强指针:__strong  默认情况下,所有的指针都是强指针 

b) 弱指针:__weak   弱指针指向的对象被回收后,弱指针会自动变为nil指针


 3ARC使用注意

1)不允许调用releaseretainretainCount

2)允许重写dealloc,但是不允许调用[super dealloc]

3@property的参数

  •      strong :成员变量是强指针(适用于OC对象类型)
  •      weak :成员变量是弱指针(适用于OC对象类型)
  •      assign : 适用于非OC对象类型

4) 以前的retain改为用strong

  

三、循环引用

1、场景示例

对于循环依赖关系来说,比方A类引用B类,同时B类也引用A类。

示例:

#import "Card.h"
@interface Person : NSObject
@property (nonatomic,retain) Card *card;
@end
 
#import "Person"
@interface Card : NSObject
@property (nonatomic,retain) Person *person;
@end 

以上代码编译会报错,而且会导致两个对象永远无法释放

 

2、解决方法

1)在.h文件中用@class来声明类,在.m文件中用到对象时再使用#import来包含类的所有东西

 (2)一端用retain,一端用assign

示例

@class Card.h
@interface Person : NSObject
@property (nonatomic,retain) Card *card;
@end
 
@class Person
@interface Card : NSObject
@property (nonatomic,assign) Person *person;
@end 

  •  当使用@class在两个类相互声明,就不会出现编译报错
  •  一端用retain一端用assign,不会出现内存泄露

3@class#import的区别

1#import方式会包含被引用类的所有信息,包括被引用类的变量和方法;@class方式只是告诉编译器在.h文件只是类的声明

2)如果有上百个头文件都#import了同一个文件,或者这些文件依次被#improt,那么一旦最开始的头文件稍有改动,后面引用到这个文件的所有类都需要重新编译一遍,这样的效率非常低,而相对来讲,使用@class方式就不会出现这种问题了

3)在.m实现文件中,如果需要引用到被引用类的实体变量或者方法时,还需要使用#import方式引入被引用类

 

4ARC模式下循环引用

一端用strong,另一端用weak,用@class来声明类

示例

@class Card.h
@interface Person : NSObject
@property (nonatomic,strong) Card *card;
@end
 
@class Person
@interface Card : NSObject
@property (nonatomic,weak) Person *person;
@end 


 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值