您的位置:首页 > Web前端

关于ios sdk5 arc(Automatic Reference Counting)的使用与理解

2012-01-06 15:04 896 查看


Understanding Automatic Reference Counting in Objective-C

from: http://longweekendmobile.com/2011/09/07/objc-automatic-reference-counting-in-xcode-explained/
Automatic Reference Counting (ARC) largely removes the burden of manual memory management, not to mention the chore of tracking down bugs caused by leaking or over-released objects! Despite its awesomeness, ARC does not let you ignore memory management altogether.

This post covers the following key aspects of ARC to help you get up and running quickly.

Reference Counted Memory: Quick Revision

How Automatic Reference Counting Works

Enabling ARC in Your Project

New Rules Enforced by ARC

ARC Qualifiers – Declared Properties

ARC Qualifiers – Regular Variables

Migrating Existing Projects to ARC

Including Code that is not ARC Compliant

Should I Use ARC?


What Has Changed?



In the time before ARC, you had to manually retain/release/autorelease objects to ensure they would “stick around” for as long as you needed them. Forgetting to send retain to an object, or releasing it too many times would cause your app to leak memory or
crash.

In Xcode 4.2, in addition to syntax checking as you type, the new Apple LLVM compiler makes it possible to offload the burden of manual memory management to the compiler, introspecting your code to decide when to release objects. Apple’s documentation describes
ARC as follows:

“Automatic Reference Counting (ARC) is a compiler-level feature that simplifies the process of managing object lifetimes (memory management) in Cocoa applications.”

This feature makes the memory management trivial most of the time, but you still need to take some responsibility for how your classes manage references to other objects.

Let’s start at the beginning …


Reference Counted Memory: Quick Review

Manually managed, reference counted memory works in iOS as follows: when creating an object using alloc/init (or other similar method), the object is returned with a retainCount of 1, meaning you havetaken ownership of the object.

?
In between alloc/init’ing an object (i.e. taking ownership) and releasing an object (i.e. relinquishing ownership), you can do with it as you wish, safe in the knowledge the object will not be deallocated whilst still in use.

Similarly, by adding an object to an autorelease pool, your object will stick around when needed and be deallocated sometime in the future when no longer needed.

?


How Automatic Reference Counting Works

Most programmers new to iOS have trouble getting their heads around reference counted memory. ARC is a pre-compilation step that adds retain/release/autorelease statements to your code for you.

This is not Garbage Collection, and reference counted memory has not disappeared, it has simply been automated. It may sound like a bit of an after thought, but considering how many features in Objective-C are implemented by pre-processing source files before
compiling, ARC is really par for the course.

When writing code with ARC enabled your code will look like this:

?
The ARC pre-compilation step will auto-magically turn it into this:

?
The diagram below (from Apple’s documentation) seems to imply that writing operative code takes almost as long to write as retain/release logic. Whilst this is not true for experienced Objective-C coders, it is probably a conservative estimate if you are new
to Objective-C. Also, when they do pop-up, memory problems can be a PITA to track down.



Source: Programming
With ARC Release Notes


Enabling ARC in Your Project

To enable ARC simply set the Objective-C Automatic Reference Counting option in your Xcode project’s Build Settings to YES. Behind the scenes this sets the -fobjc-arc compiler flag that enables ARC.




New Rules Enforced by ARC

There are a few rules you need to abide by in order to compile with ARC enabled.

1. Alloc/Init Objects

As described above, creating objects is done as before, however you must
not make anyretain/release/autorelease/retainCount calls. You also cannot be sneaky by calling their selectors indirectly: use of @selector(retain) and @selector(release) are prohibited.

2. Dealloc Methods

Generally these will be created for you. You must not make a dealloc
call directly. However you can still create a custom dealloc method if you need to release resources other than instance variables. When creating a custom dealloc method, do not call the [super dealloc] method. This will be done for you and is enforced by
the compiler.

3. Declared Properties

Before ARC, we told the compiler how to memory manage declared public properties using theassign/retain/copy parameters with the @property directive. These parameters are no longer used in ARC. Instead we have the weak/strong parameters to tell the compiler
how we want our properties treated.

4. Object Pointers in C Structures

This is also a taboo. The docs suggest storing them in a class instead of a struct. This makes sense since they would otherwise be unknown to ARC. It might cause extra some migration headaches. However, ARC can be disabled on a file by file basis. See the section
on “Including Code that is not ARC Compliant” below.

5. Casual Casting Between id and void*

Casting between id and void* data types is frequently done when handing objects between Core Foundation’s C library functions and Foundation Kit’s Objective-C library methods. This is known asToll
Free Bridging.

With ARC you must provide hints/qualifiers to tell the compiler when CF objects are moving into and out of its control for memory management. These qualifiers include __bridge, __bridge_retain and__bridge_transfer. Also you still need to call CFRetain and CFRelease
to memory manage Core Foundation objects.

This is a more advanced topic, so if you don’t know what CF objects
are, don’t worry for now.

6. @autoreleasepool instead of NSAutoReleasePool

ARC compliant code must not use NSAutoReleasePool objects, instead use the @autoreleasepool{}blocks. A good example is in the main.m file of any ARC compliant/migrated project.

?
7. Other Gotchas

Zone based memory is gone (apparently it’s not in the runtime anymore either); you cannot use NSAllocateObject or NSDeallocateObject.


ARC Qualifiers – Declared Properties

As programmers, we are used to making decisions like whether to make something a variable or a constant, locally or globally defined, etc. So too, we must decide how our properties relate to other objects. We use the strong/weak qualifiers to notify the compiler
of these relationships.

Strong References

A strong reference is a reference to an object that stops it from being deallocated. In other words it creates a owner relationship. Whereas previously you would do this:

?
Under ARC we do the following to ensure a class instance takes an ownership interest a referenced object (i.e. so it cannot be deallocated until the owner is).

?
Weak References

A weak reference is a reference to an object that does not stop it from being deallocated. In other words, it does not create an owner relationship. Whereas previously you would do this:

?
Under ARC you would do the following to ensure you do not “own” the object being referred to (e.g. typically a child object should not own its parent, so we would use a weak reference).

?


ARC Qualifiers – Regular Variables

Variable Qualifiers

The above examples illustrate declaring how our declared properties should be managed. For regular variables we have:

?
Generally speaking, these extra qualifiers don’t need to be used very
often. You might first encounter these qualifiers and others when using the migration tool. For new projects however, you generally you won’t need them and will mostly use strong/weak with your declared properties.

__strong – is the default so you don’t need to type it. This means any object created usingalloc/init is retained for the lifetime of its current scope. The “current scope” usually means the braces in which the variable is declared (i.e. a method, for loop,
if block, etc…)

__weak – means the object can be destroyed at anytime. This is only useful if the object is somehow strongly referenced somewhere else. When destroyed, a variable with __weak is set tonil.

__unsafe_unretained – is just like __weak but the poiner is not set to nil when the object is deallocated. Instead the pointer is left dangling (i.e. it no longer points to anything useful).

__autoreleasing, not to be confused with calling autorelease on an object before returning it from a method, this is used for passing objects by reference, for example when passing NSError objects by reference such as [myObject performOperationWithError:&tmp];

Source: LLVM
Clang Objective-C Automatic Reference Counting Documentation

NB: We have found @property declarations
using ‘retain’ with
ARC enabled (i.e. instead of ‘strong’)
do not cause compiler warnings and yield the same compiled result. This could change in future so stick to ‘strong’ for
clarity.


Migrating Existing Projects to ARC

Xcode 4.2 provides a conversion tool that migrates existing code to ARC, and helps you manually convert code that cannot be automatically migrated.

1. Open your non-ARC compliant project and go to Edit > Refactor > Convert to Objective-C ARC.



2. Select the build targets and contained files to convert (you exclude files in laters steps too)



3. Run Precheck and press next.



NB: When you press next the LLVM compiler will build the project in order to analyse it. If your project has any errors, you cannot proceed to the next step. If you are opening a project from a previous Xcode version for the first time, remember to Clean.

4. Inspect the proposed changes and choose to include/exclude any files. Then press save.



NB: You will also be notified of any files that cannot be migrated. Not all files (including existing libraries) need to be migrated. ARC works on a file by file basis, so see the section below on how to exclude them at compile time.

5. The migration tool will automagically set the compiler flag enabling ARC to on. You can confirm this in your project’s build settings (search for ‘reference counting’).


Including Code that is not ARC Compliant

According to Apple’s documentation: “ARC interoperates with manual reference counting code on a per-file basis. If you want to continue using manual reference counting for some files, you can do so.”

This means some files can use ARC and some files can be spared from it’s magical grasp. Here are the steps for bulk excluding files from ARC at compile time. At the time of writing, many popular libraries are not ARC ready, to get around this follow these steps:

Click on your Project in the Xcode project tree

Click on the Target

Select the Build Phases tab

Expand the Compile Sources section

Select one or more files you want to exclude from ARC

Press the return key

Type -fno-objc-arc

Press the return key again

Each file selected now has a -fno-objc-arc compiler flag set and will be excluded from ARC


Should I Use ARC?

If you are new to Objective-C, you will certainly welcome it. There is more than enough to learn at first without worrying about reference counted memory. Once you start using existing libraries though, you are sure to experience pain until you get accustomed
to explicitly excluding them from ARC pre-compilation.

If you’re already coding happily without ARC, you’re probably thinking “I don’t need it!” This may be the right answer for you — for now. Most popular libraries haven’t been converted to ARC and it does not play well with Core Foundation classes. There are
specific limitations when using CF classes listed in Apple’s documentation, and a bunch of extra qualifiers are needed to make Toll
Free Bridging work when migrating code.

From what I have seen and read, ARC is ready to use right now. However, it is probably best left to new projects until you get familiar with it. Whilst ARC is backwards compatible with iOS 4.0 onwards, weak references are only supported in iOS 5.0 onwards —
possibly another reason not to migrate everything just yet (there are work arounds to this, see the “Resources” section at the bottom of this post).

Performance wise, some
early reports claim ARC can make your projects faster – possibly due to less reliance on autorelease. However, you can also do that yourself by “coding better” and using retain/release more judiciously. But that’s just the point: ARC should always
choose the most optimised approach for your code automatically.

Right now there is some pain involved in moving to ARC, but not a lot. At Long Weekend we will leave it for new projects at first, but this is Apple’s “new” recommended approach, so you can be sure future design decisions will build on ARC and move further
away from manual reference counting.


ARC Resources:

Apple’s
ARC Programming Release Notes

Clang
documentation on LLVM complier ARC

Work
around for supporting zeroing weak references in iOS 4 and OS X 10.6

Managing
Toll Free Bridging Between Objective-C & Core Foundation Objects

WHAT
is Toll Free Bridging?

Chris
Lattner’s WWDC2011 Presentation Introducing ARC (ADC Members Only)


Other iOS Resources

If you are looking to learn more about iOS development, you might be interested in our post on the
resources we used. You might also like some of our other blog
articles on development.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: