There are two new memory management attributes for properties introduced by ARC, strong
and weak
.
Apart from copy
, which is obviously something completely different, are there any differences between strong
vs retain
and weak
vs assign
?
From my understanding, the only difference here is that weak
will assign nil
to the pointer, while assign
won't, which means the program will crash when I send a message to the pointer once it's been released. But if I use weak
, this won't ever happen, because message send to nil
won't do anything.
I don't know about any differences between strong
and retain
.
Is there any reason why should I use assign
and retain
in new projects, or are the kind of being deprecated?
strong
, weak
and unsafe_unretained
.
weak
and strong
) and 4 variable lifetime qualifiers (__strong
, __weak
, __unsafe_unretained
, __autoreleasing
). See the ARC Notes below.
assign
when compiling with ARC was an error. There are many deleted answers about this. It seems that was changed before the final release. unsafe_unretained
is the preferred attribute for many of us early adopters. For proof that unsafe_unretained
is a valid attribute look at Apple's "Programming With Objective-C" under the section "Encapsulating Data" under the subheading "Use Unsafe Unretained References for Some Classes". Which says: "For a property, this means using the unsafe_unretained attribute:"
After reading so many articles Stackoverflow posts and demo applications to check variable property attributes, I decided to put all the attributes information together:
atomic //default nonatomic strong=retain //default weak retain assign //default unsafe_unretained copy readonly readwrite //default
Below is the detailed article link where you can find above mentioned all attributes, that will definitely help you. Many thanks to all the people who give best answers here!!
Variable property attributes or Modifiers in iOS
1.strong (iOS4 = retain )
it says "keep this in the heap until I don't point to it anymore"
in other words " I'am the owner, you cannot dealloc this before aim fine with that same as retain"
You use strong only if you need to retain the object.
By default all instance variables and local variables are strong pointers.
We generally use strong for UIViewControllers (UI item's parents)
strong is used with ARC and it basically helps you , by not having to worry about the retain count of an object. ARC automatically releases it for you when you are done with it.Using the keyword strong means that you own the object.
Example:
@property (strong, nonatomic) ViewController *viewController;
@synthesize viewController;
2.weak -
it says "keep this as long as someone else points to it strongly"
the same thing as assign, no retain or release
A "weak" reference is a reference that you do not retain.
We generally use weak for IBOutlets (UIViewController's Childs).This works because the child object only needs to exist as long as the parent object does.
a weak reference is a reference that does not protect the referenced object from collection by a garbage collector.
Weak is essentially assign, a unretained property. Except the when the object is deallocated the weak pointer is automatically set to nil
Example :
@property (weak, nonatomic) IBOutlet UIButton *myButton;
@synthesize myButton;
Strong & Weak Explanation, Thanks to BJ Homer:
Imagine our object is a dog, and that the dog wants to run away (be deallocated). Strong pointers are like a leash on the dog. As long as you have the leash attached to the dog, the dog will not run away. If five people attach their leash to one dog, (five strong pointers to one object), then the dog will not run away until all five leashes are detached. Weak pointers, on the other hand, are like little kids pointing at the dog and saying "Look! A dog!" As long as the dog is still on the leash, the little kids can still see the dog, and they'll still point to it. As soon as all the leashes are detached, though, the dog runs away no matter how many little kids are pointing to it. As soon as the last strong pointer (leash) no longer points to an object, the object will be deallocated, and all weak pointers will be zeroed out.
When we use weak?
The only time you would want to use weak, is if you wanted to avoid retain cycles (e.g. the parent retains the child and the child retains the parent so neither is ever released).
3.retain = strong
it is retained, old value is released and it is assigned retain specifies the new value should be sent
retain on assignment and the old value sent -release
retain is the same as strong.
apple says if you write retain it will auto converted/work like strong only.
methods like "alloc" include an implicit "retain"
Example:
@property (nonatomic, retain) NSString *name;
@synthesize name;
4.assign
assign is the default and simply performs a variable assignment
assign is a property attribute that tells the compiler how to synthesize the property's setter implementation
I would use assign for C primitive properties and weak for weak references to Objective-C objects.
Example:
@property (nonatomic, assign) NSString *address;
@synthesize address;
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.
assign
for an object. You have to use either weak
or unsafe_unretained
(which is unsafe, obviously) if you don't want to retain the property.
assign
compiles just fine for me in ARC projects with deployment target 4.0.
retain
vs. strong
. I suppose that's mostly harmless, but I imagine it should be strong
for consistency ... or perhaps it doesn't matter. stackoverflow.com/questions/7796476/…
assign
is still valid in some cases.
nonatomic/atomic
nonatomic is much faster than atomic
always use nonatomic unless you have a very specific requirement for atomic, which should be rare (atomic doesn't guarantee thread safety - only stalls accessing the property when it's simultaneously being set by another thread)
strong/weak/assign
use strong to retain objects - although the keyword retain is synonymous, it's best to use strong instead
use weak if you only want a pointer to the object without retaining it - useful for avoid retain cycles (ie. delegates) - it will automatically nil out the pointer when the object is released
use assign for primatives - exactly like weak except it doesn't nil out the object when released (set by default)
(Optional)
copy
use it for creating a shallow copy of the object
good practice to always set immutable properties to copy - because mutable versions can be passed into immutable properties, copy will ensure that you'll always be dealing with an immutable object
if an immutable object is passed in, it will retain it - if a mutable object is passed in, it will copy it
readonly
use it to disable setting of the property (prevents code from compiling if there's an infraction)
you can change what's delivered by the getter by either changing the variable directly via its instance variable, or within the getter method itself
As far as I know, strong
and retain
are synonyms, so they do exactly the same.
Then the weak
is almost like assign
, but automatically set to nil after the object, it is pointing to, is deallocated.
That means, you can simply replace them.
However, there is one special case I've encountered, where I had to use assign
, rather than weak
. Let's say we have two properties delegateAssign
and delegateWeak
. In both is stored our delegate, that is owning us by having the only strong reference. The delegate is deallocating, so our -dealloc
method is called too.
// Our delegate is deallocating and there is no other strong ref.
- (void)dealloc {
[delegateWeak doSomething];
[delegateAssign doSomething];
}
The delegate is already in deallocation process, but still not fully deallocated. The problem is that weak
references to him are already nullified! Property delegateWeak
contains nil, but delegateAssign
contains valid object (with all properties already released and nullified, but still valid).
// Our delegate is deallocating and there is no other strong ref.
- (void)dealloc {
[delegateWeak doSomething]; // Does nothing, already nil.
[delegateAssign doSomething]; // Successful call.
}
It is quite special case, but it reveal us how those weak
variables work and when they are nullified.
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.
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.
Weak reference
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.
Strong:
Property will not Destroy but Only once you set the property to nil will the object get destroyed
By default all instance variables and local variables are strong pointers.
You use strong only if you need to retain the object.
We generally use strong for UIViewControllers (UI item's parents)
IOS 4 (non-ARC) We Can Use Retain KeyWord
IOS 5(ARC) We Can Use Strong Keyword
Example: @property (strong, nonatomic) ViewController *viewController;
@synthesize viewController;
Weak
By Default automatically get and set to nil
We generally use weak for IBOutlets (UIViewController's Childs) and delegate
the same thing as assign, no retain or release
Example : @property (weak, nonatomic) IBOutlet UIButton *myButton;
@synthesize myButton;
The differences between strong and retain:
In iOS4, strong is equal to retain
It means that you own the object and keep it in the heap until don’t point to it anymore
If you write retain it will automatically work just like strong
The differences between weak and assign:
A “weak” reference is a reference that you don’t retain and you keep it as long as someone else points to it strongly
When the object is “deallocated”, the weak pointer is automatically set to nil
A "assign" property attribute tells the compiler how to synthesize the property’s setter implementation
Success story sharing
default
mean? If I use@property (nonatomic) NSString *string
it isstrong
? Orassign
? Because both are defaults.