OBJ-C内存管理+@property参数+@class+autorelease学习笔记

========================================================================
                                    内存管理+@property参数+@class+autorelease
=========================================================================


内存管理:


对象如果不在使用了,就应该回收它的空间,防止造成内存泄漏。


OC内存管理的范围:


管理任何继承NSObject的对象,对其他的基本数据类型无效。


--------------------------------------------------------


内存管理的原理及分类


1.对象的所有权及引用计数




对象所有权概念


任何对象都可能拥有一个或多个所有者。只要一个对象至少还拥有一个所有者,它就会继续存在。


------------------------------------------------------------------------------
Cocoa所有权策略


热河自己创建的对象都归自己所有,可以使用名字以“alloc”或者“new”开头或名字中包含“copy”的方法创建对象,可以使用retain来获得一个对象的所有权。
----------------------------------------------------------------------------------------


对象的引用计数器(作用:判断对象是否要被回收)


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


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




对引用计数器的操作 
    给对象发送消息,进行相应的计数器操作。 
retain消息:使计数器+1,该方法返回对象本身 
release消息:使计数器-1(并不代表释放对象)  
retainCount消息:获得对象当前的引用计数器值  %ld %lu 
------------------------------------------------------------------------------------


对象的销毁 (dealloc方法是系统自动调用,不需要自己调用)


1.当一个对象的引用计数器为0时,那么它将被销毁,其占用的内存被系统回收。 
2.当对象被销毁时,系统会自动向对象发送一条dealloc消息,一般会重写dealloc方法,在这里释放相关的资源,dealloc就像是对象的“临终遗言”。 
3.一旦重写了dealloc方法就必须调用[super dealloc],并且放在代码块的最后调用(不能直接调用dealloc方法)。 
         4.一旦对象被回收了,那么他所占据的存储空间就不再可用,坚持使用会导致程序崩溃(野指针错误)。


注意: 
1.如果引用计数器不为0,则在程序整个运行过程当中,对象时不可能被回收的,除非程序退出。
2.任何一个对象,刚生下来,引用计数器为1.


============================================================================


OC内存管理分类


1.Manual Reference Counting;  (MRC,手动管理,苹果的底层都是用MRC)
2.Automatic Reference Counting; (ARC,自动管理,尽量使用ARC)
3.Garbage Coleection;           (iOS不支持)


ARC作为苹果的新技术,官方推荐使用ARC来管理内存,但是MRC必须理解!


============================================================================


内存管理的原则


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




谁创建,谁release
    1.如果你通过alloc,new,copy来创建了一个对象,那么你就必须调用release或者autorelease方法;
    2.不是你创建的,就不要去管;




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




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


==================================================================================
 
单个对象内存管理


最好打开僵尸对象检测!


避免使用僵尸对象的方法是,对象释放了以后,给对象赋值为nil,即:d = nil;




单个对象的内存泄漏问题:


情况1.对象创建了没有release;
情况2.没有遵守内存管理原则,retain了之后没有release;
情况3.不当使用nil;
                   Dog *d = [[Dog alloc] init];
                   d = nil;
               
                   [d eat];
                   [d release];
      
情况4.在函数内部进行了retain,但是没有release;
---------------------------------------------------------------


空指针:NULL pointer


关于nil和Nil及NULL的区别


nil:A null pointer to an Objective-C object;
Nil:A null pointer to an Objective-C class;
NULL: A null pointer to anything else;


----------------------------------------------------------


set方法内存管理


1.如果是基本类型,就按照以往的写;


2.如果是对象类型,则按下列写:


            -(void)setCar:(Car *)car
           {
                if(car!=_car){
                [_car release];
                _car = [car retain];
                }
           }


================================================================


@property参数


格式:@property (参数1,参数2)数据类型 方法名




参数类别(3类7个,面试,牢记!)


原子性:
atomic:对属性加锁,多线程下线程安全,默认值;
nonatomic:对属性不加锁,多线程下不安全,但是速度快;


读写属性:
readwrite:生成getter,setter,默认值;
readonly:只生成getter;


set方法处理:
assign:直接赋值,默认值;
retain:先release原来的值,再retain新值;(适用于OC对象类型)
copy:先release原来的值,再cooy新值;


=================================================================


@class的使用


使用格式:@class 类名;


含义:告诉编译器,这个是一个类,至于类有哪些属性和方法,此处不去检测;
好处:如果这个类的文件内容发生了改变,不需要重新编译。




在使用点语法的时候,在实现文件里面import类名头文件,这样只有运行的时候才会重新编译,效率高很多。




@class可以解决循环引入问题。


--------------------------------------------------------------


!!!!面试:


通过#import和@class引入类,有什么区别;


1.#import包含被引用类的所有信息,包括被引用类的变量和方法;@class  只是一个声明,类的具体信息在编译时候不会查看,只有运行时才会查  看;


2.@class在被引用类里声明,而在实现类要用#import引用头文件才能调用  实例变量和方法;


3.如果只使用#import引入类的头文件,则牵一发而动全身,如果有修改,  则引用到这个类的文件全部都要重新编译,效率低,而用@class则不会  出现这个问题;


4.解决了循环引入问题,即A引入B中,B又引入A中,用#import会无限循环  ,会报错;


================================================================


循环retain问题:


循环的retain会导致两个对象都会内存泄漏


防止方法:


1.让某个对象多释放一次(注意顺序)
2.推荐的方法:
         一端使用assign,一端使用retain;


=================================================================


NSString 类的内存管理问题


如果你需要的字符串在常量池中已经存在了,就不会另外分配内存空间


直接指向字符串;stringWithString; alloc initWithString 都在常量区;(带string的在常量区)
stringWithFormat; initWithFormat 在堆区;


注意:


NSString *str = [[NSString alloc] init];这样打印str的地址是在栈区!


=================================================================


autorelease基本使用


自动释放池及autorelease介绍


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


使用autorelease的好处


1.不需要再关心对象释放的时间;
2.不需要再关心什么时候调用release;


---------------------------------------------


自动释放池的使用:


1.创建自动释放池;@autoreleasepool{}
2.加入自动释放池;[对象 autorelease];注意,加入到自动释放池中以后  ,引用计数不会发生变化;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值