English Original: Understanding Automatic Reference counting in Objective-c
The automatic reference count (Automatic Reference counting, ARC) removes a lot of the burden of managing memory on the programmer's shoulders, not to mention the annoyance of tracking memory leaks. However, while arc is great, we still can't completely put the memory management thing behind the head. This article will discuss the following issues to help you quickly enter the world of arc.
- Reference count for Memory: Quick review
- How ARC works
- Open Arc in the project
- New rules applied to arc
- Arc Qualifier-declared property
- Arc Qualifier-General variable
- Porting to Arc
- Introducing code that is not compatible with arc
- Should I use arc?
|
|
What happened? Before the advent of arc, programmers had to rely on retain/relese/autorelease to make sure that the objects were just "sticking" to the moment they were needed. If you forget retain, or release an object more than once, the program will have a memory leak, or even crash directly. In Xcode 4.2, in addition to the syntax check, Apple's new LLVM compiler also picked up the drudgery of memory management, checking the code and deciding when to release the object. In Apple's documentation, ARC is defined as:
Automatic reference counting (ARC) is a compiler-level feature that simplifies the process of object lifecycle Management (memory management) in cocoa applications. ”
ARC makes memory management seem like a trivial thing for most of the time, but we still have to take some responsibility in determining how our class manages references to other objects. Well, let's officially start ... |
|
|
Reference count: Quick review Manually managed, reference-counted memory management works in iOS: When you create an object using Alloc/init (or other similar method), there is also a retaincount, with a value of 1, that shows that we have ownership of the object. ?
123 |
NSObject *obj = [[NSObject alloc] init]; // do some stuff [obj release]; |
Between the object's Alloc/init and release (that is, discarding the ownership of the object), we can handle it arbitrarily, which is safe because the system cannot reclaim objects that are in use.It is similar to adding an object to an auto-release pool, and the object will persist until it is not needed at some time in the future before it is reclaimed by the system. ?
1234 |
-(NSObject*) someMethod { NSObject *obj = [[[NSObject alloc] init] autorelease]; return obj; // will be deallocated by autorelease pool later } |
|
|
|
How ARC works Most new iOS programmers will encounter an understanding barrier to reference counting. ARC is a pre-compilation step that automatically adds a retain/release/autorelease statement to our code. ARC is not garbage collection, and the reference count doesn't go away, it just becomes automatic. It sounds like an afterthought, but if we think about how much of the objective-c is done by preprocessing the source file, you don't think so. When using arc, the code simply writes: ?
12 |
NSObject *obj = [[NSObject alloc] init]; // do some stuff |
ARC will automatically turn it into:?
123 |
NSObject *obj = [[NSObject alloc] init]; // do some stuff [obj release]; // **Added by ARC** |
From (from Apple's official documents) it looks as if the number of retain/release is fast catching up to the really useful code. Of course, this is certainly not the case of skilled, but can be seen as a conservative estimate of the novice. The code runs and it really kills people to keep track of some memory problems. Source: Programming with ARC Release Notes |
|
Open Arc in the project If you want to turn on arc, just set arc to Yes in the project's build settings. Behind the scenes, the compiler identity is actually set for-fobj-arc. New rules applied to arc If you want to use arc, you must obey some new rules. 1. Alloc/init of objects The method of creating the object is the same as before, but you must not call Retain/release/autorelease/retaincount. They cannot be secretly called by selector: @selector (retain) and @selector (release) are forbidden. |
|
2. Dealloc method ARC is called automatically for you and must not call Dealloc directly. However, if you need to release resources other than the instance variable, you can create a custom Dealloc method. But in this method, do not call [Super Dealloc]. Because ARC will help you tune it. 3. Declared properties Before arc, we used the assign/retain/copy parameter in the @property directive to tell the compiler how to manage the memory of these properties. After using arc, these parameters are void and use the Weak/strong two parameters instead. |
|
4. Object pointers in C-structures It is also forbidden to use. It is recommended in the documentation not to put them in the structure and put them in the class. Otherwise, arc doesn't know them. There may be some porting problems. However, ARC can be closed as a file. Refer to "Introducing incompatible arc code" below. 5. Temporary mutual transfer between ID and void* When we pass objects between the C function of the core foundation and the Objective-c method of the foundation kit, it is often necessary to do an ID and a void* of two types of cross-transfer. It's called free Bridging (toll bridging). If you use arc, you must tell the compiler with a hint/qualifier when the CF object enters and is out of control of the arc. Qualifiers are __bridge, __bridge_retain, and __bridge_transfer. In addition, you still need to use Cfretain and cfrelease to manage the objects of the core Foundation. This piece is already more advanced, and if you don't know what the CF object is, you don't need to worry too much. |
|
6. Replace NSAutoreleasePool with @autoreleasepool ARC-compatible code can no longer use the NSAutoreleasePool object, but instead @autoreleasepool{} blocks. A good example: ?
123456 |
int main( int argc, char *argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([ExampleAppDelegate class ])); } } |
7. Other Zone-based memory is gone (not at run time). Nsallocateobject and Nsdeallocateobject can no longer be used. |
|
Arc Qualifier-declared property As programmers, it is customary to make decisions such as declaring a quantity as a variable or constant, local or global, and so on. So, here, we also want to determine the relationship of a property to other properties. We use Strong/weak to tell the compiler about this relationship. Strong references A strong reference is a reference to an object and can prevent it from being recycled. In other words, a strong reference creates all of the relationships. Before arc, we wrote: ?
12 |
// Non-ARC Compliant Declaration @property(retain) NSObject *obj; |
Under ARC, we need to write this to ensure that the current instance obtains ownership of the referenced object (the owner is not recycled and it cannot be recycled). ?
12 |
// ARC Compliant Declaration @property(strong) NSObject *obj; |
Weak references A weak reference is a reference to an object, but it cannot be prevented from being recycled. In other words, a weak reference does not create all relationships. Before arc, we wrote: ?
12 |
// Non-ARC Compliant Declaration @property(assign) NSObject *parentObj; |
Under ARC, we need to write this to make sure that the current instance does not take ownership of the referenced object (in general, the child object should not have a parent object, which can be used with a weak reference).
12 |
// ARC Compliant Declaration @property(weak) NSObject *parentObj; |
|
|
Arc Qualifier-General variable The previous section describes how to manage properties. For regular variables, there are: ?
1234 |
__strong __weak __unsafe_unretained __autoreleasing |
In general, we do not need to use the qualifiers above. You may see a few of these when using the porting tool, but the new project is basically not needed.
- __strong: The default qualifier, which does not need to be explicitly specified. Indicates that any object created with Alloc/init is retained for the lifetime of the current scope. "Current scope" refers to the two curly braces (methods, loops, blocks, and so on) where a variable declaration statement is located.
- __weak: Indicates that the object can be destroyed at any time. It is only useful if it is strongly referenced by other objects. The __weak variable is set to nil when it is destroyed.
- __unsafe_unretained: Similar to __weak, but is not set to nil when destroyed, preserving the original value (no longer pointing to a valid thing).
- __autoreleasing: Do not confuse with autorelease, which is used to pass objects by reference, for example, by passing Nserror objects by reference: [MyObject performoperationwitherror:&tmp].
Source : http://clang.llvm.org/docs/AutomaticReferenceCounting.html#ownership Note : We found that under arc, when "retain" is used in the@property (instead of "strong"), the compiler does not make an error and produces the same result. But it may change later, so use "strong". |
|
Porting to Arc Xcode 4.2 provides a tool for porting arc, and it can also help you to manually convert the code that is not automatically ported to the past. 1. Open an arc-incompatible project and enter edit > Refactor > Convert to Objective-c arc. 2. Select the build targets and files that you want to convert (in the next steps, exclude files that do not need to be converted) 3. Run the pre-check and press Next step. Note: After pressing the next step, the LLVM compiler will start building to analyze the project. If there is an error, you cannot enter the next step. If this is the first time you've opened a project built by a low version of Xcode, perform cleanup first. |
|
Other translation versions (1) |
4. Check the tool's proposed modifications and choose whether you want to exclude a file. Then press save. Note: If a file is not ported, the tool will tell you. Not all files need to be ported (including libraries). ARC is a file-based, you can refer to the following, see how to compile a file that does not need to open arc files excluded. 5. The tool will automatically set the compiler's identity and turn on arc. You can view the build settings of the project to confirm this. |
|
introduces code that is not compatible with arc; Apple's documentation says, "ARC can be file-based and interact with code that uses manual reference counting." You can use the manual reference count on some files. "  It means that we can have some files with arc, and another part of the file. Here are the steps to bulk exclude files from arc. When I write this article, there are many popular libraries are not used arc, in order to solve this problem, please follow the following steps to do:
- in Xcode's engineering tree, click on your own project
- Click target
- Select Build Phases label
- Expand Compile Sources
- Select files that need to be excluded from Arc
- Press ENTER
- Enter-fno-objc-arc
- and press Enter
- now, the file you have selected has the-fno-objc-arc compiler identifier, which will be excluded from Arc
|
|
Should I use arc? If you are new to objective-c, you will certainly welcome arc. At first, there is too much to learn, and with arc there is no need to worry about manual counting. As you begin to reach out to some existing libraries, you will experience some pain (the translator notes: Many of the current third-party libraries are not compatible with arc), but as long as they get used to excluding them from arc, there is no problem. If you're not a novice and you're already playing high in the age of no arc, you might think, "Why would I use it?" "It might be the right answer for you--for now," he said. Because most of the popular libraries haven't been transferred to arc yet, and Arc's support for the core foundation is not good. There are some limitations when using the CF class, and when porting the code, you need to add a bunch of qualifiers to make the free bridging effective. |
|
In my opinion, the arc is now ready to use the state. However, unless you are familiar with it, it will be better to use it first in the new project. Although the arc is compatible with iOS 4.0 or more, weak references are supported only on iOS 5.0, so don't transfer everything now (there are some related articles, refer to the last "Resources" section) As for performance, it has been reported earlier that the speed will be faster after arc, and I think it may be due to reduced reliance on automatic release. While this can be done entirely by improving the code and using Retain/release better, I think the point is that arc will always automatically help you choose the best method. |
|
So far, there have been many distressing things that have been moved to arc, but not all of them. After a long weekend we will leave for a period of time to invest in new projects, but this is Apple's "new" recommendation, so you can be sure that future design decisions will continue to be powerful arc and let everyone leave using manual reference counting ARC Resources
- Apple ' s ARC programming Release Notes
- Clang documentation on LLVM complier ARC
- Work around-supporting zeroing weak references in IOS 4 and OS X 10.6
- Managing Toll free bridging between Objective-c & Core Foundation Objects
- What are Toll free bridging?
- Chris Lattner ' s WWDC2011 Presentation introducing ARC (ADC members only)
|
Understanding Objective-c's ARC