There are two new memory management attributes for properties introduced by ARC, strong
and weak
.
Apart from copy
, which is ob
The differences between strong and retain:
The differences between weak and assign:
To understand Strong and Weak reference consider below example, suppose we have method named as displayLocalVariable.
-(void)displayLocalVariable
{
NSString myName = @"ABC";
NSLog(@"My name is = %@", myName);
}
In above method scope of myName variable is limited to displayLocalVariable method, once the method gets finished myName variable which is holding the string "ABC" will get deallocated from the memory.
Now what if we want to hold the myName variable value throughout our view controller life cycle. For this we can create the property named as username which will have Strong reference to the variable myName(see self.username = myName;
in below code), as below,
@interface LoginViewController ()
@property(nonatomic,strong) NSString* username;
@property(nonatomic,weak) NSString* dummyName;
- (void)displayLocalVariable;
@end
@implementation LoginViewController
- (void)viewDidLoad
{
[super viewDidLoad];
}
-(void)viewWillAppear:(BOOL)animated
{
[self displayLocalVariable];
}
- (void)displayLocalVariable
{
NSString myName = @"ABC";
NSLog(@"My name is = %@", myName);
self.username = myName;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
@end
Now in above code you can see myName has been assigned to self.username and self.username is having a strong reference(as we declared in interface using @property) to myName(indirectly it's having Strong reference to "ABC" string). Hence String myName will not get deallocated from memory till self.username is alive.
Now consider assigning myName to dummyName which is a Weak reference, self.dummyName = myName; Unlike Strong reference Weak will hold the myName only till there is Strong reference to myName. See below code to understand Weak reference,
-(void)displayLocalVariable
{
NSString myName = @"ABC";
NSLog(@"My name is = %@", myName);
self.dummyName = myName;
}
In above code there is Weak reference to myName(i.e. self.dummyName is having Weak reference to myName) but there is no Strong reference to myName, hence self.dummyName will not be able to hold the myName value.
Now again consider the below code,
-(void)displayLocalVariable
{
NSString myName = @"ABC";
NSLog(@"My name is = %@", myName);
self.username = myName;
self.dummyName = myName;
}
In above code self.username has a Strong reference to myName, hence self.dummyName will now have a value of myName even after method ends since myName has a Strong reference associated with it.
Now whenever we make a Strong reference to a variable it's retain count get increased by one and the variable will not get deallocated retain count reaches to 0.
Hope this helps.
Clang's document on Objective-C Automatic Reference Counting (ARC) explains the ownership qualifiers and modifiers clearly:
There are four ownership qualifiers:
- __autoreleasing
- __strong
- __*unsafe_unretained*
- __weak
A type is nontrivially ownership-qualified if it is qualified with __autoreleasing, __strong, or __weak.
Then there are six ownership modifiers for declared property:
- assign implies __*unsafe_unretained* ownership.
- copy implies __strong ownership, as well as the usual behavior of copy semantics on the setter.
- retain implies __strong ownership.
- strong implies __strong ownership.
- *unsafe_unretained* implies __*unsafe_unretained* ownership.
- weak implies __weak ownership.
With the exception of weak, these modifiers are available in non-ARC modes.
Semantics wise, the ownership qualifiers have different meaning in the five managed operations: Reading, Assignment, Initialization, Destruction and Moving, in which most of times we only care about the difference in Assignment operation.
Assignment occurs when evaluating an assignment operator. The semantics vary based on the qualification:
- For __strong objects, the new pointee is first retained; second, the lvalue is loaded with primitive semantics; third, the new pointee is stored into the lvalue with primitive semantics; and finally, the old pointee is released. This is not performed atomically; external synchronization must be used to make this safe in the face of concurrent loads and stores.
- For __weak objects, the lvalue is updated to point to the new pointee, unless the new pointee is an object currently undergoing deallocation, in which case the lvalue is updated to a null pointer. This must execute atomically with respect to other assignments to the object, to reads from the object, and to the final release of the new pointee.
- For __*unsafe_unretained* objects, the new pointee is stored into the lvalue using primitive semantics.
- For __autoreleasing objects, the new pointee is retained, autoreleased, and stored into the lvalue using primitive semantics.
The other difference in Reading, Init, Destruction and Moving, please refer to Section 4.2 Semantics in the document.
Example: @property (strong, nonatomic) ViewController *viewController;
@synthesize viewController;
By Default automatically get and set to nil
Example : @property (weak, nonatomic) IBOutlet UIButton *myButton;
@synthesize myButton;
From the Transitioning to ARC Release Notes (the example in the section on property attributes).
// The following declaration is a synonym for: @property(retain) MyClass *myObject;
@property(strong) MyClass *myObject;
So strong
is the same as retain
in a property declaration.
For ARC projects I would use strong
instead of retain
, I would use assign
for C primitive properties and weak
for weak references to Objective-C objects.