OC的内存管理和@class
1、 基本原理
要想手动调用retain、release等方法,在创建项目的时候不要勾选ARC
默认情况下,Xcode是不会管僵尸对象的,使用一块被释放的内存也不会报错。为了方便调试,应该开启僵尸对象监控
如果你有个OC对象类型的成员变量,就必须管理这个成员变量的内存。比如有个Book *_book
- (void)setBook:(Book *)book{
if (book != _book) {
[_book release];
_book = [book retain];
}
}
- (void)dealloc {
[_book release];
[super dealloc];
}
对于循环依赖关系来说,比方A类引用B类,同时B类也引用A类
这种代码编译会报错。当使用@class在两个类相互声明,就不会出现编译报错
使用 @class 类名; 就可以引用一个类,说明一下它是一个类
7、Autorelease
(一)基本用法
(1)会将对象放到一个自动释放池中
(2)当自动释放池被销毁时,会对池子里的所有对象做一次release
(3)会返回对象本身
(4)调用完autorelease方法后,对象的计数器不受影响(销毁时影响)
(二)好处
(1)不需要再关心对象释放的时间
(2)不需要再关心什么时候调用release
(三)使用注意
(1)占用内存较大的对象,不要随便使用autorelease,应该使用release来精确控制
(2)占用内存较小的对象使用autorelease,没有太大的影响
(四)错误写法
(1)连续调用多次autorelease,释放池销毁时执行两次release(-1吗?)
(2)Alloc之后调用了autorelease,之后又调用了release。
(五)自动释放池
(1)在ios程序运行过程中,会创建无数个池子,这些池子都是以栈结构(先进后出)存在的。
(2)当一个对象调用autorelease时,会将这个对象放到位于栈顶的释放池中
(六)自动释放池的创建方式
(1)ios 5.0以前的创建方式
NSAutoreleasePool *pool=[[NSAutoreleasePool alloc] init];
`````````````````
[pool release];//[pool drain];用于mac
(2)Ios5.0以后
@autoreleasepool
{//开始代表创建自动释放池
·······
}//结束代表销毁自动释放池
(七)Autorelease注意
(1)系统自带的方法中,如果不包含alloc new copy等,则这些方法返回的对象都是autorelease的,如[NSDate date];
(2)开发中经常会写一些类方法来快速创建一个autorelease对象,创建对象时不要直接使用类名,而是使用self
Book *book = [[Book alloc] init];
[book release];
Book *book = [[[Book alloc] init] autorelease];
// 不要再调用[book release];
+ (id)book {
return [[[Book alloc] init] autorelease];
}
外界调用[Book book]时,根本不用考虑在什么时候释放返回的Book对象
NSNumber *n = [NSNumber numberWithInt:100];
NSString *s = [NSString stringWithFormat:@"jack"];
NSString *s2 = @"rose";
8、ARC内存管理机制
(一)ARC的判断准则:
只要没有强指针指向对象,对象就会被释放。
(二)指针分类:
(1)强指针:默认的情况下,所有的指针都是强指针,关键字strong
(2)弱指针:_ _weak关键字修饰的指针
声明一个弱指针如下:
_ _weak Person *p;
ARC中,只要弱指针指向的对象不在了,就直接把弱指针做清空操作。
_ _weak Person *p=[[Person alloc] init];//不合理,对象一创建出来就被释放掉,对象释放掉后,ARC把指针自动清零。
ARC中在property处不再使用retain,而是使用strong,在dealloc中不需要再[super dealloc]。
@property(nonatomic,strong)Dog *dog;// 意味着生成的成员变量_dog是一个强指针,相当于以前的retain。
如果换成是弱指针,则换成weak,不需要加_ _。
(三)ARC的特点总结:
(1)不允许调用release,retain,retainCount
(2)不允许重写dealloc,但是不允许调用[super dealloc]
(3)@property的参数:
Strong:相当于原来的retain(适用于OC对象类型),成员变量是强指针
Weak:相当于原来的assign,(适用于oc对象类型),成员变量是弱指针
Assign:适用于非OC对象类型(基础类型)
(四)补充
让程序兼容ARC和非ARC部分。转变为非ARC -fno-objc-arc 转变为ARC的, -f-objc-arc 。
ARC也需要考虑循环引用问题:一端使用retain,另一端使用assign。
提示:字符串是特殊的对象,但不需要使用release手动释放,这种字符串对象默认就是autorelease的,不用额外的去管内存。
1 // 2 // main.m 3 // 01-arc的基本使用 4 // 5 // Created by apple on 13-8-11. 6 // Copyright (c) 2013年 itcast. All rights reserved. 7 // 8 9 #import <Foundation/Foundation.h> 10 #import "Person.h" 11 #import "Dog.h" 12 13 14 /* 15 ARC的判断准则:只要没有强指针指向对象,就会释放对象 16 17 18 1.ARC特点 19 1> 不允许调用release、retain、retainCount 20 2> 允许重写dealloc,但是不允许调用[super dealloc] 21 3> @property的参数 22 * strong :成员变量是强指针(适用于OC对象类型) 23 * weak :成员变量是弱指针(适用于OC对象类型) 24 * assign : 适用于非OC对象类型 25 4> 以前的retain改为用strong 26 27 指针分2种: 28 1> 强指针:默认情况下,所有的指针都是强指针 __strong 29 2> 弱指针:__weak 30 31 */ 32 33 int main() 34 { 35 Dog *d = [[Dog alloc] init]; 36 37 Person *p = [[Person alloc] init]; 38 p.dog = d; 39 40 d = nil; 41 42 NSLog(@"%@", p.dog); 43 44 return 0; 45 } 46 47 void test() 48 { 49 // 错误写法(没有意义的写法) 50 __weak Person *p = [[Person alloc] init]; 51 52 53 NSLog(@"%@", p); 54 55 NSLog(@"------------"); 56 }
总结:
一、计数器的基本操作
1> retain : +1
2> release :-1
3> retainCount : 获得计数器
二、set方法的内存管理
1> set方法的实现
- (void)setCar:(Car *)car
{
if ( _car != car )
{
[_car release];
_car = [car retain];
}
}
2> dealloc方法的实现(不要直接调用dealloc)
- (void)dealloc
{
[_car release];
[super dealloc];
}
三、@property参数
1> OC对象类型
@property (nonatomic, retain) 类名 *属性名;
@property (nonatomic, retain) Car *car;
@property (nonatomic, retain) id car;
// 被retain过的属性,必须在dealloc方法中release属性
- (void)dealloc
{
[_car release];
[super dealloc];
}
2> 非OC对象类型(int\float\enum\struct)
@property (nonatomic, assign) 类型名称 属性名;
@property (nonatomic, assign) int age;
四、autorelease
1.系统自带的方法中,如果不包含alloc、new、copy,那么这些方法返回的对象都是已经autorelease过的
[NSString stringWithFormat:....];
[NSDate date];
2.开发中经常写一些类方法快速创建一个autorelease的对象
* 创建对象的时候不要直接使用类名,用self