Automatic Reference Counting
In Objective-C and Swift programming, Automatic Reference Counting (ARC) is a memory management enhancement where the burden of keeping track of an object's reference count is lifted from the programmer to the compiler.[1] In traditional Objective-C, the programmer would send retain
and release
messages to objects in order to mark objects for deallocation or to prevent deallocation.[2] Under ARC, the compiler does this automatically by examining the source code and then adding the retain
and release
messages in the compiled code.[3]
ARC differs from Cocoa's garbage collection [4] in that there is no background process doing the deallocation of objects.[5] Unlike garbage collection, ARC does not handle reference cycles automatically; it is up to the programmer to break cycles using weak references.[6]
Apple Inc. delivered a fully featured version of ARC in 2011 for application development on its Mac OS X Lion and iOS 5 operating systems.[7] Before that, a limited version of ARC (ARCLiteCite error: The <ref>
tag has too many names (see the help page).) was supported in Xcode 4.2 or later, Mac OS X 10.6 "Snow Leopard" or later, and iOS 4.0 or later. Mac OS X 10.7 "Lion" or iOS 5 is recommended to use all the features, including weak reference support. Apple's Swift language, introduced in 2014, uses ARC for memory management.
Rules when using ARC in Objective C
The following rules are enforced by the compiler when ARC is turned on:
- You cannot call
retain
,release
,retainCount
,autorelease
, ordealloc
.[8]
- The compiler automatically inserts the correct calls at compile time, including messaging
[super dealloc]
in an override of dealloc.
- Code example without ARC:
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
}
- Code example with ARC:
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
// no need to call [super dealloc] here
}
- You cannot cast directly between
id
andvoid *
.[8] This includes casting between Foundation objects and Core Foundation objects.
- You must use special casts, or calls to special functions, to tell the compiler more information about the object's lifetime.
- Code example without ARC:
- (NSString *)giveMeAString
{
CFStringRef myString = [self someMethodThatCreatesACFString];
NSString *newString = (NSString *)myString;
return [newString autorelease];
}
- Code example with ARC and a cast:
- (NSString *)giveMeAString
{
CFStringRef myString = [self someMethodThatCreatesACFString]; // retain count is 1
NSString *newString = (__bridge_transfer NSString *)myString; // the ownership has now been transferred into ARC
return newString;
}
- Code example with ARC and a function call:
- (NSString *)giveMeAString
{
CFStringRef myString = [self someMethodThatCreatesACFString]; // retain count is 1
NSString *newString = (NSString *)CFBridgingRelease(myString); // the ownership has now been transferred into ARC
return newString;
}
- You cannot use
NSAutoreleasePool
objects.[8]
- You must use the
@autoreleasepool
syntax. This syntax is now available for all Objective-C modes.
- Code example without ARC:
- (void)loopThroughArray:(NSArray *)array
{
for (id object in array) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// create a lot of temporary objects
[pool drain];
}
}
- Code example with ARC:
- (void)loopThroughArray:(NSArray *)array
{
for (id object in array) {
@autoreleasepool {
// create a lot of temporary objects
}
}
}
- You cannot call the functions
NSAllocateObject
andNSDeallocateObject
[8] - You cannot use object pointers in C structures (
struct
s)[8] - You cannot use memory zones (
NSZone
)[8] - To properly cooperate with non-ARC code, you also cannot create a method or a declared property (unless you explicitly choose a different getter) that begins with "copy".[8]
Property Declarations
ARC introduces some new property declaration attributes, some of them replacing the old attributes.
Without ARC | With ARC | With ARCLite [Note 1] |
---|---|---|
retain |
strong
| |
assign (for object types) |
weak |
unsafe_unretained
|
copy
|
- ^ ARCLite is ARC but without zeroing weak references (used when deploying to a less-capable operating environment than ARC requires).
Zeroing Weak References
Zeroing weak references is a feature in Objective-C ARC that automatically clears (sets to nil
) weak-reference local variables, instance variables, and declared properties immediately before the object being pointed to begins deallocation. This ensures that the pointer goes to either a valid object or nil
, and avoids dangling pointers. Prior to the introduction of this feature, "weak references" referred to references that were not retaining, but were not set to nil
when the object they pointed to was deallocated (equivalent to unsafe_unretained
in ARC), thus possibly leading to a dangling pointer. The programmer typically had to ensure that when an object is being deallocated to set all possible weak references to it to nil
manually. Zeroing weak references obviates the need to do this.
Zeroing weak references are indicated by using the declared property attribute weak
or by using the variable attribute __weak
.
Zeroing weak references are only available in Mac OS X 10.7 "Lion" or later and iOS 5 or later, because they require additional support from the Objective-C runtime. However, some OS X classes do not currently support weak references.[8] Code that uses ARC but needs to support versions of the OS older than those above cannot use zeroing weak references, and therefore must use unsafe_unretained
weak references. There exists a third-party library called PLWeakCompatibility [1] that allows one to use zeroing weak references even on these older OS versions.
Converting to ARC
Xcode 4.2 or later provides a way to convert code to ARC.[9] As of Xcode 4.5, it is found by choosing Edit > Refactor > Convert to Objective-C ARC... Although Xcode will automatically convert most code, some code may have to be converted manually. Xcode will inform the developer when more complex use cases arise, such as when a variable is declared inside an autorelease pool and used outside it or when two objects need to be toll-free bridged with special casts.
ARC in Swift
Swift uses ARC to manage memory. To allow the programmer to prevent strong reference cycles from occurring, Swift provides the weak and unowned keywords. Weak references must be optional variables, since they can change and become nil.
A closure within a class can also create a strong reference cycle by capturing self references. The programmer can indicate which self references should be treated as weak or unowned using a capture list.[10]
See also
References
- ^ Siracusa, John. "Automatic Reference Counting". Mac OS X 10.7 Lion: the Ars Technica review. http://arstechnica.com. Retrieved 15 August 2012.
{{cite web}}
: External link in
(help)|publisher=
- ^ Cruz, José R.C. "Automatic Reference Counting on iOS". Dr.Dobb's. Retrieved 21 August 2012.
- ^ Kochan, Stephen G. (2011). Programming in Objective-C (4th ed.). Boston, Mass.: Addison-Wesley. p. 408. ISBN 978-0321811905.
- ^ "NSGarbageCollector Class Reference". Mac Developer Library. Apple Inc. 23 July 2012. Retrieved 9 June 1014.
{{cite web}}
: Check date values in:|accessdate=
(help) - ^ Hoffman, Kevin (2012). Sams teach yourself Mac OS X Lion app development in 24 hours. Indianapolis, Ind.: Sams. p. 73. ISBN 9780672335815.
- ^ "General". Automatic Reference Counting. http://clang.llvm.org. Retrieved 15 August 2012.
{{cite web}}
: External link in
(help)|publisher=
- ^ Sakamoto, Kazuki (2012). Pro Multithreading and Memory Management for Ios and OS X With Arc, Grand Central Dispatch and Blocks. Apress. pp. xii. ISBN 978-1430241164.
- ^ a b c d e f g h "Transitioning to ARC Release Notes". Retrieved 14 September 2012.
- ^ "What's New in Xcode 4.2 – Automatic Reference Counting". Apple Inc. Retrieved 3 October 2012.
- ^ https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html