本文主要是介绍iOS ------ MRC,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
一,MRC
- MRC:
Manual reference Counting
与ARC是两种不同的内存管理机制。ARC是自动引用计数,有编译器在编译时自动插入内存管理代码。而MRC是手动引用计数,开发者需要手动管理对象的引用计数。 - 开发者需要手动调用retain,release,autorelease等方法来增加或减少对象的引用计数,当对象的引用计数为0时,对象的内存将被释放。
- 设置MRC:将自动引用计数关掉后就为MRC
//new方式和alloc init方式一样,只不过我们习惯了分两步走。
//MJPerson *person = [MJPerson new];
MJPerson *person = [[MJPerson alloc] init]; //1
//中间写我们想要的代码
[person release]; // 0或者:
@autoreleasepool {
MJPerson *person = [[[MJPerson alloc] init] autorelease]; //1
//中间写我们想要的代码
}
二,MRC的setter方法
MJPerson里面拥有MJDog,在MJPerson里面重写setDog方法。
- (void)setDog:(MJDog *)dog
{if (_dog != dog) {[_dog release]; _dog = [dog retain];
}
1,为什么要释放旧值?
如果将新值直接赋给实例变量,而没有堆旧值进行适当的释放操作,旧值的引用计数就从不会减少,对象的内存也不会释放,这就会导致内存泄漏。
2,为什么要retain新值?
当一个对象被复制给一个实例变量,为了确保对象在使用时保持有效,需要增加对象的引用计,这样可以保证在其他地方意外释放对象
3,为什么要检查对象是否相等?
如果_dog和传入的dog是同一个对象,旧值release后引用计数就为0,旧值就会被释放,这时再retain新值就报错。
如果时基本数据类型,就不用进行内存管理,如果是OC对象,setter方法就要这样写。
MRC下的@property只会生成setter和getter方法的声明,如果想生成_age成员变量和setter、getter方法的实现还要使用@synthesize关键字。
三,野指针和空指针
1,空指针
- 指的是没有指向存储空间的指针,(里面存的是nil)
- 给空指针发消息是没有任何反应
NSObject *a = [[NSObject alloc] init]; //执行完引用计数为1[a release]; //执行完引用计数为 0,实例对象被释放。a = nil; //此时,a变为了空指针。[a release]; // 再给空指针a发送消息就不会报错了。[a release];
2,野指针
- 只要一个对象被释放,我们就称这个对象为僵尸对象(不能再使用的对象)
- 当一个指针指向一个僵尸对象,我们就称这个指针为也指针
- 只要给也指针发送消息就会报错
NSObject *b = [[NSObject alloc] init]; //执行完引用计数为1[b release]; //执行完引用计数为 0,实例对象被释放。[b release]; // 此时,a 就变成了野指针,再给野指针 a 发送消息就会报错
四,关键字的使用
下面话就看看使用不同的关键字修饰@property并且使用@synthesize
关键字,生成setter和getter方法实现有什么不同
1,assign修饰
使用assign生成的setter方法没有内存管理相关的东西,所以assign一般用来修饰基本数据类型,默认情况下就是assign
- (void)setAge:(int)age
{_age = age;
}- (int)age
{return _age;
}
2,使用retain修饰
使用retain修饰,生成的setter方法有内存管理相关的东西,所以retain一般用来修饰对象类型。
- (void)setDog:(MJDog *)dog
{if (_dog != dog) {[_dog release];_dog = [dog retain];}
}- (MJDog *)dog
{return _dog;
}
五,自动生成释放池(AutoreleasePool
)
autorelease
是一种支持引用计数的内存管理方式,只要给对象发送autorelease消息,会将对象放在一个自动释放池(AutoreleasePool
)中,当自动释放池被销毁时,会对池子里的所有对象做一次release操作。其本质就是对对象的release的调用延迟,延长对象的生命周期。
这里只是发送release消息,如果当时的引用计数依旧不为0,则对象依然不会被释放,autorelease方法返回对象本身,且调用完autorelease方法后,对象的计数器不变。
autorelease的使用方法
- 使用NSAutoreleasePool创建
NSAutoreleasePool* autoreleasePool = [[NSAutoreleasePool alloc] init];//创建自动释放池
Person* p = [[[Person alloc] init] autorelease];//方法释放池
[autoreleasePool drain];//销毁自动释放池
- 使用@autoreleasePool创建
@autoreleasepool
{ // 创建一个自动释放池Person *p = [[Person new] autorelease];// 将代码写到这里就放入了自动释放池
} // 销毁自动释放池(会给池子中所有对象发送一条 release 消息)
六,MRC的优点
- 精准控制内存管理:MRC允许开发者手动管理对象的引用计数,可以精准地控制对象的生命周期
- 兼用型好:MRC在iOS早期使用较多,许多老的代码仍然使用MRC进行内存管理
在使用ARC
时,开发者只需要关注对象的强引用和弱引用,无需关心对象的引用计数。而在使用MRC
时,开发者需要手动管理对象的引用计数,需要仔细地在合适的地方调用retain
、release
或autorelease
等方法,以避免内存泄漏和野指针问题。
总体而言,ARC是iOS开发中推荐使用的内存管理机制。它可以帮助开发者更专注于业务逻辑的实现,减少了大量的内存管理代码,提高了代码的可读性和可维护性。同时,ARC在性能上也不会比MRC有明显的劣势,因为编译器会在编译时进行优化,生成高效的内存管理代码。
这篇关于iOS ------ MRC的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!