使用在函数参数转换的从属关键词
当在函数调用的参数中使用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禁止使用强指针,下面是可能的解决方案:
-
使用类来代替结构。
这是最好的方式。
-
如果在使用类有性能问题(比如你需要一个很大的结构的数组),那么可以使用void*来代替。
这需要显式的转换,下面会有讨论。
-
把这个变量用__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 *的转换(包括核心功能中的类型)。