========================================================================
内存管理+@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];注意,加入到自动释放池中以后 ,引用计数不会发生变化;
内存管理+@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];注意,加入到自动释放池中以后 ,引用计数不会发生变化;