2013年3月15日星期五

ARC



Transitioning to ARC Release Notes

  1. ARC is supported in Xcode 4.2 for OS X v10.6 and v10.7 (64-bit applications) and for iOS 4 and iOS 5. Weak references are not supported in OS X v10.6 and iOS 4.
  2. ARC 需要知道它的作用域,这样才能正确的释放这个对象。
  3. sortedResults 在 @autoreleasepool 的作用域中定义, 在它的外部不能被访问到。 为了修正这个问题,你需要将变量的定义放到创建 NSAutoreleasePool 的上面。
  4. You also need to take care with objects passed by reference. The following code will work:
    NSError *error;
    BOOL OK = [myObject performOperationWithError:&error];
    if (!OK) {
    // Report the error.
    // ...
    However, the error declaration is implicitly:
    NSError * __strong e;
    and the method declaration would typically be:
    -(BOOL)performOperationWithError:(NSError * __autoreleasing *)error;
    The compiler therefore rewrites the code:
    NSError * __strong error;
    NSError * __autoreleasing tmp = error;
    BOOL OK = [myObject performOperationWithError:&tmp];
    error = tmp;
    if (!OK) {
    // Report the error.
    // ...
    The mismatch between the local variable declaration (__strong) and the parameter (__autoreleasing) causes the compiler to create the temporary variable. You can get the original pointer by declaring the parameter id __strong * when you take the address of a __strong variable. Alternatively you can declare the variable as __autoreleasing.

  5. You cannot give an accessor a name that begins with new. This in turn means that you can’t, for example, declare a property whose name begins with new unless you specify a different getter:
    // Won't work:
    @property NSString *newTitle;
    // Works:
    @property (getter=theNewTitle) NSString *newTitle;
  6. Use Lifetime Qualifiers to Avoid Strong Reference Cycles

    You can use lifetime qualifiers to avoid strong reference cycles. For example, typically if you have a graph of objects arranged in a parent-child hierarchy and parents need to refer to their children and vice versa, then you make the parent-to-child relationship strong and the child-to-parent relationship weak. Other situations may be more subtle, particularly when they involve block objects.
    In manual reference counting mode, __block id x; has the effect of not retaining x. In ARC mode, __block id x; defaults to retaining x (just like all other values). To get the manual reference counting mode behavior under ARC, you could use __unsafe_unretained __block id x;. As the name__unsafe_unretained implies, however, having a non-retained variable is dangerous (because it can dangle) and is therefore discouraged. Two better options are to either use __weak (if you don’t need to support iOS 4 or OS X v10.6), or set the __block value to nil to break the retain cycle.
    The following code fragment illustrates this issue using a pattern that is sometimes used in manual reference counting.
    MyViewController *myController = [[MyViewController alloc] init…];
    // ...
    myController.completionHandler =  ^(NSInteger result) {
    [myController dismissViewControllerAnimated:YES completion:nil];
    };
    [self presentViewController:myController animated:YES completion:^{
    [myController release];
    }];
    As described, instead, you can use a __block qualifier and set the myController variable to nil in the completion handler:
    MyViewController * __block myController = [[MyViewController alloc] init…];
    // ...
    myController.completionHandler =  ^(NSInteger result) {
    [myController dismissViewControllerAnimated:YES completion:nil];
    myController = nil;
    };
    Alternatively, you can use a temporary __weak variable. The following example illustrates a simple implementation:
    MyViewController *myController = [[MyViewController alloc] init…];
    // ...
    MyViewController * __weak weakMyViewController = myController;
    myController.completionHandler =  ^(NSInteger result) {
    [weakMyViewController dismissViewControllerAnimated:YES completion:nil];
    };
    For non-trivial cycles, however, you should use:
    MyViewController *myController = [[MyViewController alloc] init…];
    // ...
    MyViewController * __weak weakMyController = myController;
    myController.completionHandler =  ^(NSInteger result) {
    MyViewController *strongMyController = weakMyController;
    if (strongMyController) {
    // ...
    [strongMyController dismissViewControllerAnimated:YES completion:nil];
    // ...
    }
    else {
    // Probably nothing...
    }
    };
    In some cases you can use __unsafe_unretained if the class isn’t __weak compatible. This can, however, become impractical for nontrivial cycles because it can be hard or impossible to validate that the __unsafe_unretained pointer is still valid and still points to the same object in question.


strong 用来修饰强引用的属性
@property (strong) SomeClass * aObject; 
对应原来的
@property (retain) SomeClass * aObject; 和 @property (copy) SomeClass * aObject; 

weak 用来修饰弱引用的属性
@property (weak) SomeClass * aObject; 
对应原来的 
@property (assign) SomeClass * aObject; 

__weak, __strong 用来修饰变量,此外还有 __unsafe_unretained, __autoreleasing 都是用来修饰变量的。
__strong 是缺省的关键词。
__weak 声明了一个可以自动 nil 化的弱引用。
__unsafe_unretained 声明一个弱应用,但是不会自动nil化,也就是说,如果所指向的内存区域被释放了,这个指针就是一个野指针了。
__autoreleasing 用来修饰一个函数的参数,这个参数会在函数返回的时候被自动释放。

没有评论:

发表评论