佳为好友

转:关于ARC的一些规则

创建:2012.02.27

主要内容来自:
还有部分内容来自Cookbook,但是cookbook介绍的太过简略很深奥,不易掌握,因此没有全部摘录。以后还要在细看看。
Automatic Reference Counting, or ARC for short
+++
ARC is a feature of the new LLVM 3.0 compiler. Your existing projects most likely use the older GCC 4.2 or LLVM-GCC compilers
+++
It is important to realize that ARC is a feature of the Objective-C compiler and therefore all the ARC stuff happens when you build your app. ARC is not a runtime feature (except for one small part, the weak pointer system), nor is it *garbage collection* that you may know from other languages. 
+++
All that ARC does is insert retains and releases into your code when it compiles it, exactly where you would have put them yourself. That makes ARC just as fast as manually managed code, and sometimes even a bit faster because it can perform certain optimizations under the hood.
When the pointer gets a new value or ceases to exist, the associated object is released.
no longer call retain, release and autorelease and retainCount.
+++
__strong,__weak,__unsafe_unretained,__autoreleasing
默认情况下,所有的instance variables and local variables都是strong指针。
__autoreleasing—These variables are used with object pointer arguments (id *), which are autoreleased on return.The NSError class offers the most common use case for these variables—for example,int result = doSomething(arg, arg, arg, &error);. Convenience methods also return autoreleased objects.
+++
对象被释放后,其上的weak指针将自动变为nil。
+++
下面的代码是无效的:
__weak NSString *str = [[NSString alloc] initWithFormat:...];
NSLog(@"%@", str);  // will output "(null)"
字符串对象没有拥有者(因为str是weak
指针),并且这个字符串对象将在被创建之后立刻被释放掉了。XCode将给你一个警告(“Warning: assigning retained object to weak variable; object will be released after assignment”)
+++
Weak is the recommended relationship for all *outlet* properties. 
如果将IBOutlet的属性设置为weak,那么在进入到viewDidUnload之前,它们就会被释放,并设置为nil
所以在viewDidUnload将不能使用这些IBOutlet了。
+++
With ARC, all strong, weak, and autoreleasing stack variables are automatically initialized with nil.
+++
NSError __autoreleasing *error;
// Retrieve the icon's file attributes 
NSString *iconLocation = [[NSBundle mainBundle] pathForResource:@"icon" ofType:@"png"];
NSDictionary *dictionary = [[NSFileManager defaultManager] attributesOfItemAtPath:iconLocation error:&error];
if (!dictionary) 
NSLog(@"Could not get attribute information: %@", error);
+++
ARC continues to use assign qualifiers for non-object values such as int and CGRect.
+++
These property declarations change from this,
@property (retain, nonatomic)
to this:
@property (strong, nonatomic)
Under ARC you are not allowed to call release, nor [super dealloc].
+++
By the way, in your dealloc method you can still use your instance variables because they haven’t been released yet at that point. That doesn’t happen until after dealloc returns.
+++
As a best practice, if you define something as a property, then you should always use it as a property. The only places where you should access the property’s backing instance variable directly are in init and when you provide a custom getter and setter.
+++
@property (nonatomic, readonly) NSString *result;
You must explicitly state whether you want this property to be strong, weak or unsafe_unretained. Most of the time, strong is the proper answer:
@property (nonatomic, strong, readonly) NSString *result;
+++
Autorelease didn’t go away with ARC, even though you never directly call the [autorelease] method on objects anymore. Any time you return an object from a method whose name doesn’t start with alloc, init, copy, mutableCopy or new, the ARC compiler will autorelease it for you. These objects still end up in an autorelease pool. 
Control ARC’s return behavior by declaring NS_RETURNS_RETAINED and NS_RETURNS_NOT_RETAINED. For example,
- (NSString *) copyName NS_RETURNS_NOT_RETAINED;
returns an autoreleased object to non-ARC code, even though the name starts with the phrase “copy.”
The big difference with before is that the NSAutoreleasePool has been retired in favor of a new language construct, @autoreleasepool.
The conversion tool turned our main() function from this,
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, nil, 
  NSStringFromClass([AppDelegate class]));
[pool release];
return retVal;
into this:
@autoreleasepool {
  int retVal = UIApplicationMain(argc, argv, nil, 
    NSStringFromClass([AppDelegate class]));
    return retVal;
}
+++
You may have some code that creates its own autorelease pool:
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
 
// . . . do calculations . . .
 
NSArray* sortedResults = 
  [[filteredResults sortedArrayUsingSelector:@selector(compare:)] 
    retain];
 
[pool release];
return [sortedResults autorelease];
The conversion tool needs to turn that into something like this:
NSArray* sortedResults = nil;
@autoreleasepool
{
  // . . . do calculations . . .       
  sortedResults = [filteredResults sortedArrayUsingSelector:@
    selector(compare:)];
}
return sortedResults;
+++
“Switch case is in protected scope”
You get this error when your code does the following:
switch (X)
{
    case Y:
        NSString *s = ...;
        break;
}
This is no longer allowed. If you declare new pointer variables inside a case statement you must enclose the whole thing in curlies:
switch (X)
{
    case Y:
    {
        NSString *s = ...;
        break;
    }
}
Now it is clear what the scope of the variable is, which ARC needs to know in order to release the object at the right moment.
+++
One of the restrictions of ARC is that you can no longer put Objective-C objects inside C structs. The following code is no longer valid:
typedef struct
{
    UIImage *selectedImage;
    UIImage *disabledImage;
}
ButtonImages; 
+++
Automatic Reference Counting also has a few limitations. For starters, ARC only works on Objective-C objects. If your app uses Core Foundation or malloc() and free(), then you’re still responsible for doing the memory management there.
+++
    * __bridge_transfer: Give ARC ownership
    * __bridge_retained: Relieve ARC of its ownership
    * __bridge:ARC对于此对象的内存的态度保持原来的状态。即如果ARC原来是持有该对象的,那么仍然持有。如果ARC原来是不持有该对象的,那么现在仍然不持有。
    
    也可以使用CFBridgingRelease()来替代__bridge_transfer,它更清晰一些。
    
    CFBridgingRetain来替代__bridge_retained。即:
NSString *s1 = [[NSString alloc] initWithFormat:@"Hello, %@!", name];
CFStringRef s2 = (__bridge_retained CFStringRef)s1;
// do something with s2
// . . .
CFRelease(s2);
或者:
CFStringRef s2 = CFBridgingRetain(s1);
// . . .
CFRelease(s2);
+++
Note: Not all Objective-C and Core Foundation objects that sound alike are toll-free bridged. For example, CGImage and UIImage cannot be cast to each another, and neither can CGColor and UIColor. This page lists the types that can be used interchangeably.
+++
To summarize:
    * When changing ownership from Core Foundation to Objective-C you use CFBridgingRelease().
    * When changing ownership from Objective-C to Core Foundation you use CFBridgingRetain().
    * When you want to use one type temporarily as if it were another without ownership change, you use __bridge.
    
+++
ARC even combines well with C++. With a few restrictions you can also use ARC on iOS 4, which should only help to speed up the adoption.   
If you must deploy to iOS 4.x, use __unsafe_unretained qualifiers instead of weak.This is functionally equivalent to old- style assign properties and will work on old-style OS runtimes
+++
Never use NSAllocateObject or NSDeallocateObject.
+++
You must assign the result of [super init], typically as self = [super init]. You probably already do this, as well as checking to see whether self is nil. Just keep doing that.
+++
常见的内存错误:
id obj = [array objectAtIndex:0];
[array removeObjectAtIndex:0];
NSLog(@"%@", obj);
+++++

posted on 2012-12-29 11:12 佳为好友 阅读(318) 评论(0)  编辑 收藏 引用 所属分类: 非UI


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


导航

<2012年12月>
2526272829301
2345678
9101112131415
16171819202122
23242526272829
303112345

留言簿(1)

随笔分类

搜索

最新评论

评论排行榜