iOS 内存管理

2019-01-09  本文已影响0人  鐧箪

iOS 无论是在MRC 还是ARC情况下 OC 都是用引用计数来管理内存!

内存管理的原则是: 谁创建 谁来释放   谁引用,谁管理

例如MRC下:

NSObject * a = [NSObject alloc] init];    a 引用计数为 1

NSObject * b; //相同类型局部变量b

b =  [a retain]   //b这个时候可以使用a     a的引用计数+1  =  2

[a realse]; a的引用计数为1

[a realse]; a的引用计数为0

alloc 、new、  copy、 mutableCopy  引用计数 = 1     生成并持有对象 

retain  引用计数+1  并持有这个对于  

strong  引用计数+1   MRC下会做一次retain ARC下省略 

addobject 类似的  想要持有这个对象  引用计数+1  

release 引用计数 - 1 

dealloc 引用计数为0的时候调用

ARC管理方法:

在ARC内存管理机制中,id和其他对象类型变量必须是以下四个ownership qualifiers其中一个来修饰:

__strong   强引用

__weak  弱引用 

__unsafe_unretained   它是不安全的。它跟__weak相似,被它修饰的变量都不持有对象的所有权,但当变量指向的对象的RC为0时,变量并不设置为nil,而是继续保存对象的地址;这样的话,对象有可能已经释放,但继续访问,就会造成非法访问(Invalid Access)

__autoreleasing

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

// put object into pool

id obj = [[NSObject alloc] init];

[obj autorelease];

[pool drain];

/* 超过autorelease pool作用域范围时,obj会自动调用release方法 */

引入ARC之后,写法比之前更加简洁:

@autoreleasepool {

    id __autoreleasing obj = [[NSObject alloc] init];

}

ARC需要注意的事项?

1.过度使用 block 之后,无法解决循环引用问题

由于Core Foundation 框架并不支持 ARC,此时编译器不知道该如何处理这个同时有 ObjC 指针和 CFTypeRef 指向的对象,所以除了转换类型,还需指定内存管理所有权的改变,可通过 __bridge、__bridge_retained 和 CFBridgingRetain、__bridge_transfer 和 CFBridgingRelease。

2.遇到底层 Core Foundation 对象,需要自己手工管理它们的引用计数时,我们需转换关键字,作为桥接转换以解决 Core Foundation 对象与 Objective-C 对象相对转换的问题:

__bridge:使用__bridge标记可以在不修改相关对象的引用计数的情况下,将对象从Core Foundation框架数据类型转换为Foundation框架数据类型(反之亦然)。

CF和OC对象转化时只涉及对象类型不涉及对象所有权的转化

只是声明类型转变,但是不做内存管理规则的转变

CFStringRef s1 = (__bridge CFStringRef) [[NSString alloc] initWithFormat:@"Hello, %@!", name];

只是做了 NSString 到 CFStringRef 的转化,但管理规则未变,依然要用 Objective-C 类型的 ARC 来管理 s1,你不能用 CFRelease() 去释放 s1。

__bridge_retained:会将相关对象的引用计数加 1,并且可以将Core Foundation框架数据类型对象转换为Foundation框架数据类型对象,并从ARC接管对象的所有权。

NSString *s1 = [[NSString alloc] initWithFormat:@"Hello, %@!", name];

CFStringRef s2 = (__bridge_retained CFStringRef)s1;

// or CFStringRef s2 = (CFStringRef)CFBridgingRetain(s1);

// do something with s2

//...

CFRelease(s2); // 注意要在使用结束后加这个

__bridge_transfer:可以将Foundation框架数据类型对象转换为Core Foundation框架数据类型对象,并且会将对象的所有权交给ARC管理,也就是说引用计数交由ARC管理;

__bridge_transfer or CFBridgingRelease



CFStringRef result = CFURLCreateStringByAddingPercentEscapes(. . .);

NSString *s = (__bridge_transfer NSString *)result;

//or NSString *s = (NSString *)CFBridgingRelease(result);

上一篇下一篇

猜你喜欢

热点阅读