美文网首页
iOS 内存管理

iOS 内存管理

作者: 鐧箪 | 来源:发表于2019-01-09 11:28 被阅读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);

    相关文章

      网友评论

          本文标题:iOS 内存管理

          本文链接:https://www.haomeiwen.com/subject/wprwrqtx.html