[黑马程序员]14[OC语言]OC内存管理部分学习笔记总结

来源:互联网 发布:c语言经典第五版pdf 编辑:程序博客网 时间:2024/06/06 02:11

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



OC内存管理

 

1.    内存管理基本概念+总结

 

// 内存管理管理范围:任何继承了NSObject的对象,对其他基本数据类型无效

 

// 栈空间的东西程序运行完毕会自动回收,对象是在堆空间的,必须手动回收

 

// 内存管理-02-引用计数器

 

// 每个OC对象都有自己的引用计数器,表示对象被引用的次数

 

// 每个对象都会专门分配4个字节的空间来存放自己的引用计数器,新对象刚刚诞生的时候计数器值为1

 

// 当使用alloc,new,copy创建一个新对象的时候,新对象的引用计数器默认为1

 

// 计数器为0,对象空间就会被回收,如果不为零,除非整个程序被完全退出,否则占用的内存会一直占用

 

 

// 4.引用计数器的操作

 

// 1>给对象发送一条retain消息,可以使引用计数器+1(retain方法返回对象本身)

 

// 2>给对象发送一条release消息,可以使引用计数器-1

 

// 3>可以给对象发送retainCount消息获得当前的引用计数器值

 

 

// 5.对象的销毁

 

// 当一个对象被销毁时,系统会自动向对象发送一条dealloc消息

 

// 一般会重写dealloc方法,在这里释放相关资源,dealloc就像对象的遗言

 

// 一旦重写了dealloc方法,就必须调用[superdealloc],并且放在最后面调用

 

// 注意,非常重要,不要直接调用dealloc方法

 

//一旦对象被回收了,它占用的内存就不可再用,坚持使用会导致程序崩溃(即野指针错误)

 

一,计数器的基本操作

1>retian : +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, retian) 类名 *属性名;

@property (nonatomic,retain) Car *car;

@property (nonatomic,retain)id car;

 

//retain过的属性,必须在dealloc方法中release属性

- (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过的

[NSStringstringWithFormat:...];

[NSDate date];

 

2.开发中经常写一些类方法快速创建一个autorelease的对象

*创建对象的时候不要直接用类名,用self

 

2. remain与release-多文件与set

 

// alloc,必须调用一次release,retain,必须调用一次release

 

// 自己创建的小孩,自己得负责

 

// 内存管理-04-野指针和空指针

 

// 计数器为0为被回收,成为僵尸对象,这时仍然指向僵尸对象(不可用内存对象)的指针叫做野指针

 

// EXC_BAD_ACCESS报错,访问了一块坏的内存(已经被回收,不可再使用的内存),又叫做野指针错误

 

// 所指内存为僵尸对象的时候,为了防止成为野指针成为野指针错误,这时应该把指针清空 p= nil;

 

// OC中不存在空指针错误,给空指针发送消息,不报错

 

// 人死不能复生,变成僵尸对象后不能通过发retain复生

 

 

// 1.release,release方法的基本使用

 

// 2.野指针,僵尸对象

 

// 计算机管理总结

 

// 1.方法的基本使用

 

// 1>retain ;计数器+1;会返回对象本身

 

// 2>release :计数器-1,没有返回值

 

// 3>retaincount:获取当前的计数器

 

// 4>dealloc

// * 当一个对象要被回收的时候,就会调用

// * 一定要调用[superdealloc],这句调用要放在最后面

 

// 2.概念

// 1>僵尸对象:所占内存已经被回收的对象,僵尸对象不能再被使用

// 2>野指针:指向僵尸对象(不可用内存)的指针,给野指针法消息会报错

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

 

// 加一个指向对象,调用一次retain使计数器+1;少一个对象,调用一次release使计数器-1;计数器为零的时候,房间,book撤销;

 

// 1.Person, Book举例

 

// 2.QQ堂游戏开房间举例,玩家对象,房间对象

 

// >多房间跳转,撤销当前房间的指向,调用一次当前指向房间的release;然后指向新的房间,调用一次新房间的retain

 

// >谁创建,release(alloc,new,copy);

 

// >retain,release(责任);

 

// >原则:有始有终,负责任

 

// 多对象内存管理-03-代码演示

#import "Person.h"

#import "Book.h"

 

int main()

{

    Book * b = [[Bookalloc]init];

   

    Person *p1 = [[Personalloc]init];

   

    [p1 setBook:b];

    //[b retain]; // p1想占有b这本数,那么调用一次bretain,这是隐形调用

   

    [b release];

    b = nil;

   

    [p1 release];

    p1 = nil;

   

    return0;

}

 

@implementation Person

- (void)setCar:(Car *)car

{

    if (car !=_car)//setcar不是当前的才释放旧的,换新的,否则不管

    {

        //在这里需要对旧车做一次release

        [_carrelease];

       

        _car = [car retain];

    }

}

 

- (Car *)car

{

    return_car;

}

 

- (void)setAge:(int)age

{

    _age = age;

}

 

- (int)age

{

    return_age;

}

 

- (void)dealloc

{

    [_carrelease];

   

    NSLog(@"personrelease");

   

    [superdealloc];

}

@end

 

 

// 内存管理代码规范:

// 1.只要调用了allocation,必须有release(autorelease)

 

// 2.set方法的代码规范:

// 1>基本数据类型:直接复制

// - (void)setAge:](int)age

// {

//    _age = age;

// }

//

// 2> OC对象类型

// - (void)setCar:](Car*)car

// {

//    //1.先判断是不是新传进来对象

//    if(car !=_car)

//    {

//        //2.对就对象做一次release

//        [_car release];

//

//        //3.对新对象做一次retain

//        _car = [car retain];

//    }

// }

//

// 3.dealloc方法的代码规范

// 1>一定要[superdealloc],而且放在最后面

// 2>self(当前)所拥有的其他对象做一次release

// - (void)dealloc

// {

//    [_car release];

//    [super dealloc];

// }

 

//1.set方法内存管理相关的参数

// * retain: release旧值,retain新值(适用于OC对象类型)

// * assign:直接赋值(默认,适用于非OC对象类型)

// * copy: release旧值,copy新值

 

//2.是否要生成set方法

//* readwrite:同时生成settergetter

//* readonly:只会生成getter的声明

 

//3.多线程管理

//* nonatomic:性能高生成setter方法的时候不要设置多线程

//* atomic: 性能低(默认)//不要用这个

 

//4.settergetter方法的名称

 

2.    autorelease与ARC机制

 

// 2.autorelease的好处

// 1>不用再关系对象释放的时间

// 2>不用再关系什么时候调用release

 

// 3.autorelease的使用注意

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

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

 

// 4.错误写法

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

// 2> 连续多次调用autorelease,具体的各个对象释放时间

 

// 5.自动释放池

// 1>ios程序运行过程中,会创建无数个池子.这些池子都是以栈结构存在(先进后出)

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

// (程序每隔一段时间会自动生成和方法一定数量的池子,通常发生在程序与用户发生交互的时候)

 

 

// 6.自动释放池的创建方式

// 1>ios 5.0

// NSAutoreleasePool *pool= [[NSAutoreleasePool alloc] init];

// [pool release];  // [pool drain]

// 2>ios 5.0开始

// @autorelease{}

 

 

 

// autorelease的应用

 

#import "Person.h"

 

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

 

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

// 1> 创建对象时不要直接使用类,一般用self(为了分类和子类的适应性)

 

#import "GoodPerson.h"

 

int main()

{

    @autoreleasepool {

       

        Person *p2 = [Person personWithAge:100];

       

        GoodPerson *p = [GoodPerson personWithAge:10];

       

        p.money =100;

    }

   

    return0;

}

 

 

int test()

{

    Person *p = [[Personalloc]init];

   

    p.age =200;

   

    [p release];

   

    @autoreleasepool {

       

        //        Person *p2 = [Person person];

        //

        //        p2.age = 100;

        //        Person *p2 = [PersonpersonWithAge:100];

       

        NSString *str = @"12313132";

       

        NSString *str2 = [NSString stringWithFormat:@"age is %d",10];

       

        NSString *num = [[NSNumber alloc] initWithInt:10];

       

        NSNumber *num2 = [NSNumber numberWithInt:10];

       

    }

   

    return0;

}

 

//OC里没有包的概念,同名文件即使在不同文件夹中也会认为是同一文件

 

//在创建对象的时候尽量使用self

 

 

// ARC是一个编译器特性,编译器在编译的时候检测哪里需要插release,不是java的垃圾回收.

 

// 01-ARC-基本原理

 

// ARC的判断准则:只要没有强指针指向对象,就会释放对象

 

// 指针分两种

// 1>强直阵:默认情况下,所有的指针都是强指针 __strong

// 2>弱指针:__weak

 

 

// ARC-02-@propertystrongweak

 

// 1.ARC特点

// 1>不允许调用release,retain,rtainCount

// 2>允许重写重写dealloc,但是不允许调用[superdealloc]

// 3>@property的参数

// *strong:成员变量是强指针(使用于OC对象类型)

// *weak:成员变量是弱指针(适用于OC对象类型)

// *assign:适用于非OC对象类型

// 4>以前的retain改为用strong

 

 

 

// ARC-03-XcodeARC转换功能

 

//Xcode-edit-Refactor-transfer to ARC

 

// 多个文件,某个文件不要ARC,buildphases里找到对应.m,输入"-fno-obj-arc"即可,相反情况用"-f-obj-arc"

 

 

 

 

// ARC-04-循环引用

 

// 之前非ARC"-身份证"循环引用问题,"-主人"问题

// 1>ARC1端用retain,另一端用assign

//1>ARC   1端用strong,另一端用weak

0 0