oc的内存管理和@property的属性关键字

我们来看看内存分布

栈:存放的是局部变量,这块存储区域是系统管理的,不需要我们管理。

堆:存放的是OC中的对象,这块存储区域是程序员自己管理的。它是动态存储区域。

常量区:存放的是常量,这块存储区域是系统管理的。

全局区:存放的时全局变量和静态变量,这块存储区域是系统管理的。

代码区:存放分是代码,这块区域是系统管理的。


指针存放在栈中,而指针指向的变量是存放在堆中。因此当指针被回收的时候,它的对象并不会被回收。

MRC(Manual Reference Counting)手动内存管理|手动引用计数

在OC的内存管理中:引进了引用计数。

1、当一个对象被建立的时候,它的引用计数是1。

2、当一个对象的引用计数是0的时候,这个对象将会被回收。


引用计数

1、release 引用计数-1

2、retain  引用计数+1 (这里还会返回一个调用该方法的对象)

3、retainCount 返回当前对象的引用计数

手动内存管理黄金法则:

谁调用alloc\new\retain\copy\mutableCopy,谁就调用相应的release|autorelease;

当你需要某一个对象的时候,那么就给它发送一条retain方法。

当你不需要某一个对象的时候,那么就给它发送一条release方法。

内存管理不当产生的后果:

1、如果不再使用的对象没有被回收,就会照成内存泄露。会导致程序闪退。

2、如果正在被使用的对象被回收了,就会照成野指针错误。会导致程序崩溃。


内存管理中的关键字(@property)

retain在setter和getter方法中加入一些内存管理的代码(当属性是一个普通的OC对象的时候就使用retain)

assign表示的时直接复制,不会产生内存管理的代码(当属性是一个基本数据类型的时候就使用assign)

copy表示复制对象(当属性是NSString数据类型的时候就使用copy)

在@property中的关键字还有

  生成多线程线程安全的关键字

nonatomic表示非原子的,不会生成线程安全的代码,速度比较快。iOS中的属性一般都是使用它。

atomic表示原子的,它会生成线程安全的代码。

控制权限的关键字

readonly表示可以读,只能生成getter方法。

readwrite表示可以读可以写,生成getter和setter方法的声明与实现。

修改方法名称的关键字

getter表示修改生成的getter方法的名称。一般情况下,BOOL类型的属性的getter方法都是以is开头的。

setter表示修改生成的setter方法的名称,不过一般不修改。


循环引用:

指针的是两个对象中,你中有我,我中有你。跟java中的一对一很相似。至于产生内存泄露的原因主要是相互之前强指针指着对方,感觉跟java里面谁来hibernate设置谁来管理对方。(在这里我们引入了强指针与弱指针在ARC中会提到,这里不做解释。)

解决循环引用的方式:让其中一方设置为assign。

多个对象之间不要封闭环,如果出现封闭的环,那么环中所有的对象将得不到释放。解决的方法,让其中一端为虚线。


自动释放池:(自动释放池是一个栈)

autorelease:延长对象的释放生命周期。作用:把对象放进离自己最近的那个自动释放池中。(它与对象在何地创建没有关系,只要标记上就放进离自己最近的那个自动释放池中。)

当自动释放池销毁的时候,它会把放在池中的所有对象进行一次release操作。

调用几次autorelease,在自动释放池销毁的时候就调用几次release操作。

在自动释放池中,只要是使用getter方法|构造方法返回来的对象都是放在池中。

ARC(automatic Reference Counting)自动内存管理

ARC中编译器的特性:编译器会在适当的时候,加入内存管理的代码。

(_strong强指针标识符,默认所有的指针都是强指针)

作用:只要强指针指向的对象,那么这个对象就不会被释放。

 只要没有强指针指向的对象,那么这个对象将会被立即被释放。

(_weak弱指针标识符)

弱指针:不参与内存管理,对内存管理没有影响。不会影响对象的回收。

注意:不要使用一个弱指针指向一个刚刚创建出来的对象,一旦这样做,刚创建出来的对象马上销毁,在OC中也是自动销毁机制。

当出现循环引用的时候就必须要让一端使用弱指针。


在ARC中的@property

strong  对所有的普通OC对象

copy 对字符串

assign 基本数据类型

weak 对于循环应用的时候,必须保证一段使用的是weak。如果不这样你懂的。


ARC中的自动释放池机制:

只要是通过方法返回来的对象都是存放在ARC的自动释放池中。



以上的测试代码如下:

#import"Person.h"

#import "Room.h"

int main(int argc, const char * argv[]) {

//    Person *person = [[Person alloc]init];

//    long count = [person retainCount];

//    NSLog(@"%zd",count);

//    [person retain];

//    NSLog(@"%zd",[person retainCount]);

//    [person release];

//    NSLog(@"%zd",person.retainCount);

//    [person release];

//    //测试OC中有没有空指针异常(发现系统不会报错,并且什么都没做)

//    person = nil;

//    NSLog(@"%zd",person.retainCount);


//多对象的内存管理

    Person *person = [[Person alloc]init];//1

    Room *room = [[Room alloc]init];//1

    [person setRoom: room];//room = 2

    [room release];// room = 1

    room = nil;

    [person release];// person =0 room =0;

    person = nil;

    return 0;

}


/

#import <Foundation/Foundation.h>

@class Room;


@interface Person : NSObject


@property(nonatomic,retain)Room *room;


//- (void)setRoom:(Room *)room;

@end


#import "Person.h"

#import "Room.h"


@implementation Person


//- (void)setRoom:(Room *)room{//这个跟@property(nonatomic,retain)Room *room生成的方法一致

//    //成员对象一创建的时候,就会被初始化为nil

//    //此处要加一个判断,判断两个对象是否是同一个对象。如果不相同,才需要内存管理的代码。

//    if(_room != room){

//        [_room release];

//        _room = [room retain];

//    }

    [room retain];

    _room = room;

//    //等于(因为retain会返回对象)

    _room = [room retain];

    [_room release];

    _room = [room retain];

//  

//}

//永远不要试图自己调用这个方法

- (void)dealloc{

    

//    [_room release];

//    _room = nil;

    //等价于

    self.room = nil;//因为nil调用方法不会有任何变换。因此在上面的set方法中,不会让计数器加一

    

    //它会在对象回收的时候被打印出来

    NSLog(@"Person对象被回收了");

    

    //这个方法中必须调用父类的该方法,并且必须放在最后

    [super dealloc];

}

@end

/

@interface Room : NSObject


@end


#import "Room.h"


@implementation Room

- (void)dealloc{

    NSLog(@"Room对象被回收了");

    //这个方法中必须调用父类的该方法,并且必须放在最后

    [super dealloc];

}

@end

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值