Objective-C ARC: strong vs retain and weak vs assign
Asked Answered
S

8

382

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?

Scathe answered 19/1, 2012 at 14:27 Comment(3)
There are three new memory management attributes for properties introduced by ARC strong, weak and unsafe_unretained.Natasha
@Natasha There are two property attributes (weak and strong) and 4 variable lifetime qualifiers (__strong, __weak, __unsafe_unretained, __autoreleasing). See the ARC Notes below.Prophets
@SnowCrash There was a version of Xcode, likely a developer preview, in which using 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:"Natasha
L
236

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.

Lanchow answered 19/1, 2012 at 14:52 Comment(9)
In fact, under ARC it is a compilation error to use 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.Augustine
assign compiles just fine for me in ARC projects with deployment target 4.0.Spadiceous
@Pascal: weak references aren't allowed in deployment targets where the os is not 5.0 or higher. So for older projects you can still use assign, but if you move to newer versions you have to switch to weakShamefaced
Looks like Xcode 4 (with ARC) generates NSManagedObject subclasses using retain vs. strong. I suppose that's mostly harmless, but I imagine it should be strong for consistency ... or perhaps it doesn't matter. #7796976Descriptive
weak is not valid for non-objects. For example, one must use assign when defining an NSInteger property.Wembley
@Lanchow Yes, your answer is spot-on. I was reacting to @Mattia. I was pointing out that assign is still valid in some cases.Wembley
Since llvm 3.1 strong is the default attribute for properties when using ARC: See clang.llvm.org/docs/… and https://mcmap.net/q/15482/-in-objective-c-with-arc-is-it-true-that-we-usually-only-need-to-specify-nonatomic-as-property-attributes. So there is no need anymore to declare strong explicitly when using ARC.Lotus
if strong is same as retain then why apple introduce the strong? can anybody help with this?Ganger
@SatishMavani Because, when they introduced ARC, they wanted to get people away from thinking in terms of retain and retain counts and get them into thinking about ownership relations in the object graph.Lanchow
A
622

After reading so many articles Stackoverflow posts and demo applications to check variable property attributes, I decided to put all the attributes information together:

  1. atomic //default
  2. nonatomic
  3. strong=retain //default
  4. weak
  5. retain
  6. assign //default
  7. unsafe_unretained
  8. copy
  9. readonly
  10. 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;
Atonsah answered 21/3, 2013 at 7:33 Comment(7)
2. "a weak reference is a reference that does not protect the referenced object from collection by a garbage collector" - there is no such thing in objective c as garbage collector;Headreach
3. "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" - Everything wrong. IBOutlet - just word reserved to say that this property can be linked via IB. 'IBOutlets properties' are NOT childs!!! They are other objects! And as we know 'weak' doesn't not prevent Object from deallocation, so UIViewController can't control how long it exist! But its desired. Because someone else keep's a strong pointer to it. And it's superview (IBOutlet property's view superview). All views live in hierarchy.Headreach
and this hierarchy is managed by iOS automatically. Read about MVC concept. I mean when ViewContorller is being presented iOS loads it's view hierarchy on screen (creating missing views). When other ViewController is presented, this first hierarchy of views is deallocated. But if you have 'strong' in ViewController, then this view can't be deallocated, when it's off screen. Which could have hard impact on device memory and cause of slowdown of app. (Of course device have a lot of memory and you'd definitely be fine on 5-10 screen app, but in huge app you'll get into trouble)Headreach
When we use weak? 1. For UI objects, 2. delegates , 3. blocks (weakSelf should be used instead of self to avoid memory cycles (as was mentioned above)Headreach
There is one mistake in this great answer - strong - "ARC automatically releases it for you when you are done with it", this is not right. ARC will automatically release weak objects when there are no pointers to them. Strong - is synonym to retain, so the object is retained and it is our responsibility to make the object nilMatz
@RDC, What does default mean? If I use @property (nonatomic) NSString *string it is strong? Or assign? Because both are defaults.Dobbs
how come when you use (strong) in non-arc it doesn't throw an error or warning that it can only be used in arc project @HeadreachHulburt
L
236

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.

Lanchow answered 19/1, 2012 at 14:52 Comment(9)
In fact, under ARC it is a compilation error to use 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.Augustine
assign compiles just fine for me in ARC projects with deployment target 4.0.Spadiceous
@Pascal: weak references aren't allowed in deployment targets where the os is not 5.0 or higher. So for older projects you can still use assign, but if you move to newer versions you have to switch to weakShamefaced
Looks like Xcode 4 (with ARC) generates NSManagedObject subclasses using retain vs. strong. I suppose that's mostly harmless, but I imagine it should be strong for consistency ... or perhaps it doesn't matter. #7796976Descriptive
weak is not valid for non-objects. For example, one must use assign when defining an NSInteger property.Wembley
@Lanchow Yes, your answer is spot-on. I was reacting to @Mattia. I was pointing out that assign is still valid in some cases.Wembley
Since llvm 3.1 strong is the default attribute for properties when using ARC: See clang.llvm.org/docs/… and https://mcmap.net/q/15482/-in-objective-c-with-arc-is-it-true-that-we-usually-only-need-to-specify-nonatomic-as-property-attributes. So there is no need anymore to declare strong explicitly when using ARC.Lotus
if strong is same as retain then why apple introduce the strong? can anybody help with this?Ganger
@SatishMavani Because, when they introduced ARC, they wanted to get people away from thinking in terms of retain and retain counts and get them into thinking about ownership relations in the object graph.Lanchow
P
45

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
Punchy answered 8/10, 2014 at 18:50 Comment(2)
@Sakthimuthiah is right, you must to correct your answer.Gizzard
@Sakthimuthiah is incorrect (and anyone else who says it is). Atomic does NOT make it thread safe, though it can be easily mistaken due to its behavior. Please read: #12347736Huffish
I
39

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.

Ium answered 27/1, 2013 at 9:47 Comment(1)
#9429000Whydah
C
21

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.

Cherub answered 22/10, 2013 at 9:20 Comment(0)
D
6

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.

Draughtsman answered 11/10, 2018 at 12:36 Comment(0)
C
4

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;

Corella answered 26/1, 2017 at 7:41 Comment(0)
H
2

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
Hackery answered 26/4, 2015 at 6:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.