MRC:手动内存管理
ARC:默认是ARC:automatic
Reference Count,自动引用计数器
Person
*p = [[Person alloc] init];
//p就叫做对象的所有者,默认对象出生时,alloc后,对象引用计数器值为1
//当我们看到new alloc创建对象时,引用计数器值为1.
NSLog(@"%lu",p.retainCount);
//retainCount:能够输出对象引用计数器的值
引用计数器的操作
想要管理对象占用的内存,就要学会操作引用计数器。
引用计数器的常见操作:
retain消息:使计数器+1(该方法返回对象本身)
release消息:使计数器-1(不代表释放对象)
retainCount:获得对象当前的应用计数器值,输出:%ld,%lu
注意:release不代表销毁对象,仅仅是引用计数器-1.
怎么判断对象被释放
dealloc方法:只要调用了这个方法,就代表对象即将被释放。
僵尸对象:已经被释放的对象。
野指针:指向僵尸对象的指针。
空指针:指向nil的指针,给空指针发送消息(调用方法)不会报任何错误。
但是,如果没有一个统一的释放原则,name就会造成代码的混乱,会都可以释放,好比一个公司所有的领导没有分工一样,任何事,任何一个领导都可以插一嘴。所以,释放对象要遵循一个原则,那就是谁创建,谁释放。
如果在程序结束后,对象没有被释放,此时称为内存泄漏。
释放对象时,若要查看释放情况,重写dealloc方法:
- (void)dealloc
{
NSLog(@"%d号房间被释放啦",_fno);
//这里必须调用父类的dealloc
[super dealloc];
}
@property参数
格式:@property(参数1,参数2)数据类型 方法名
Setter:改set方法的名字
Getter改get方法的名字
什么是内存管理:(面试必问)
管理堆区内存的分配和释放
分配内存:newalloc copy
释放内存:release
@class
@class Cat;//仅仅告诉编译器Cat是一个猫类,可以声明一个对象。
建议:头文件引入一个类的时候,使用@class。
具体使用:
在.h文件中使用@class引用一个类
在.m文件中使用#import包含这个类的.h文件
引入一个类的方法有两种
#import和@class
区别:
#import方式会包含被引用类的所有信息,包括被引用类的变量和方法;@class方式只是告诉编译器在A.h文件中B
*b只是类的声明,具体这个类里有什么信息,这里不需要知道,等实现文件中真正要用到时,才会真正去查看B类中信息。
使用@class方式由于只需要知道被引用类(B类)的名称就可以了,而在实现类由于要用到被引用类中的实体变量和方法,所以需要使#import来包含被引用类的头文件。
通过上面两点也很容易知道在编译效率上,如果有上百个头文件都#import了同一个文件,或者这些文件一次被#import(A->B,B->C,C->D.。。),一旦最开始的头文件稍有改动,后面引用到这个文件的所有类都需要重新编译一遍,这样的效率也是可想而知的。而相对来讲,使用@class方式就不会出现这种问题了;
所以我们实际开发中尽量在.h头文件中使用@class
对于循环依赖关系来说,比方A类引用B类,B类也引用A类
这样嵌套包含的代码编译就会报错
当使用@class在两个类相互声明,就不会出现编译器报错
面试题:#import和@class的区别。
作用上的区别
import会包含引用类的所有信息(内容),包括引用类的变量和方法
@class仅仅是告诉编译器有这么一个类,具体这个类里有什么信息,完全不知道。
效率上的区别
如果有上百个头文件都#import了同一个文件,或者这些文件依次被#import,那么一旦最开始的头文件稍有改动,后面引用到这个文件的所有类都需要重新编译一遍,编译效率非常低相对来讲,使用@class方式就不会出现这种问题了。
对于循环retain的情况,对象不能够释放,此时只能让一方使用assign。
@property(nonatomic,assign)Girl *girl;
NSString
由于字符串是一个特殊的类,因此OC给NSString的retainCount赋值了一个很大的值,因此开发的时候不用考虑NSString的内存管理问题。
自动释放池(ARC)
int main(int argc, const char* argv[]) {
@autoreleasepool {//自动释放池
//autorelease:当对象调用这个方法时,就把对象放到了自动释放池中
Person *p = [[[Person alloc]init]autorelease];
//不用关注对象什么时候被释放
}//出了花括号,会对池子里面的所有调用了autorelease方法的对象,做一次release
return 0;
}
ARC特点总结
不允许调用release,retain,retainCount
允许重写dealloc,但是不允许调用[super dealloc]
@property的参数
strong:相当于原来的retain(适用于OC对象类型),成员变量是强指针
weak:相当于原来的assign(适用于OC对象类型),成员变量是弱指针
assign:适用于非OC对象类型(基础类型)
ARC使用注意事项
ARC中,只要弱指针指向的对象不在了,就直接把弱指针做清空(赋值为nil)操作
_weak Person *p = [[Person alloc]init];//不合理,对象一创建出来就被释放掉,对象释放掉后,ARC把指针设置为nil
ARC在Property处不在使用retain,而是使用strong,在dealloc中不需要在[super
dealloc],@property(nonatomic,strong)Dog *dog;//意味着生成的成员变量_dog是一个强指针,相当于以前的retain。
如果换成是弱指针,则换成weak,不需要加_.