• IOS 5 ARC机制 (三)


    使用在函数参数转换的从属关键词

    当在函数调用的参数中使用Objective-C和基础核心实例的转换的时候,你需要告诉编译关于这个传入参数的所属信息。这些基础核心实例的所属规则定义在基础核心内存管理规则中(参考 Memory Management Programming Guide for Core Foundation);Objective-C实例的规则定义在Advanced Memory Management Programming Guide.

    在下面的代码片段中,传入函数的CGGradientCreateWithColors 的数组是需要转换的。byarrayWithObjects:函数返回的实例所属没有传入参数,转换关键词使用__bridge.

    NSArray *colors = [NSArray arrayWithObjects:[[UIColor darkGrayColor] CGColor],[[UIColor lightGrayColor] CGColor], nil];CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef)colors, locations);

    下例演示了函数中的代码片段的情况,注意所有核心内存管理函数都是遵循基础核心内存管理规则的。

    - (void)drawRect:(CGRect)rect {CGContextRef ctx = UIGraphicsGetCurrentContext();CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();CGFloat locations[2] = {0.0, 1.0};NSArray *colors = [NSArray arrayWithObjects:[[UIColor darkGrayColor] CGColor],[[UIColor lightGrayColor] CGColor], nil];CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef)colors, locations);CGColorSpaceRelease(colorSpace); // Release owned Core Foundation object.CGPoint startPoint = CGPointMake(0.0, 0.0);CGPoint endPoint = CGPointMake(CGRectGetMaxX(self.bounds), CGRectGetMaxY(self.bounds));CGContextDrawLinearGradient(ctx, gradient, startPoint, endPoint,kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation);CGGradientRelease(gradient); // Release owned Core Foundation object.}

    这个问题的细节在 “Managing Toll-Free Bridging”里面讨论。

    转换旧工程的要点

    在扩展旧工程的时候,你需要注意下面事项.

    你不能调用retain, release,或者 autorelease.

    同样,下面的代码也不能写:

    while ([x retainCount]) { [x release]; }
    你不能调用dealloc.

    一般情况下,在单例模式下,或者需要替换实例的时候,可能需要在init函数里面调用dealloc函数。对于单例模式,你可以使用共享模式来替代。因为后者在init里面不需要调用dealloc,在你从新对self赋值的时候,原内存就被释放了。

    你不用使用NSAutoreleasePool对象

    新的@autoreleasepool{}结构是作为一个替代。它比原先的NSAutoreleasePool快六倍。@autoreleasepool同样在手动管理内存的方式下能够工作。

    在init方法中,ARC要求把[super init]赋值给self。

    下面的代码在ARC模式下是不合法的。

    [super init];

    简单的改成下面这个样就可以了:

    self = [super init];

    一般还需要检查返回值:

    self = [super init];if (self) {...
    你不能实现自己的retain和release方法。

    实现自己的retain或release方法会破坏弱指针,这里有一些理由阻止你这样做:

    • 性能.

      请不要实现这些函数,因为在NSObject中的实现快多了,如果你发现问题,那么需要改掉这些问题,而不是再次实现这些函数。

    • 为了实现弱指针To implement a custom weak pointer system.

      使用__weak来替代这些函数的实现.

    • 为了实现单例模式。

      使用共享模式。或者,使用类级别函数,这样根本不需要申请实例。

    如果你发现不得不实现retain或者release函数,那么请在类中实现下面的函数:

    -(BOOL)supportsWeakPointers { return NO; }

    上面的函数阻止为你的类生成弱指针。不过还是强烈建议你使用其他的方式来避免实现这些函数。

    不能在C语言的结构中使用strong ids。

    比如,下面的代码不能被编译:

    struct X { id x; float y; };

    因为x并定义强引用,那么编译器就不能为它生成按照的管理代码。例如,如果x以及被赋值,那么在这个结构的指针被free前,必须先释放这些x指向的内存,但是由于是ARC模式,所以这些内存就被泄漏了,所以在C语言的结构中,ARC禁止使用强指针,下面是可能的解决方案:

    1. 使用类来代替结构。

      这是最好的方式。

    2. 如果在使用类有性能问题(比如你需要一个很大的结构的数组),那么可以使用void*来代替。

      这需要显式的转换,下面会有讨论。

    3. 把这个变量用__unsafe_unretained修饰。

      这个会对下面的情况会有帮助:

      struct x { NSString *S; int X; } StaticArray[] = {@"foo", 42,@"bar, 97,...};

      你可以这样定义结构:

      struct x { __unsafe_unretained NSString *S; int X; }

      这样的写法可能会有很大的问题,如果在指针里面的实例被释放了。but it is very useful for things that are known to be around forever like constant string literals.

    你不能直接进行id和void *的转换(包括核心功能中的类型)。
  • 相关阅读:
    03、SqlMapConfig.xml配置文件
    02、Mybatis整体架构介绍
    01、Mybatis快速入门
    Struts2学习笔记(十一)——文件上传
    Struts2学习笔记(十)——自定义拦截器
    Struts2学习笔记(九)——数据校验
    Struts2学习笔记(八)——国际化
    Struts2学习笔记(七)——类型转换
    Struts2学习笔记(六)——Action处理请求参数
    Struts2学习笔记(五)——Action访问Servlet API
  • 原文地址:https://www.cnblogs.com/greywolf/p/2782351.html
Copyright © 2020-2023  润新知