ChatGPT解决这个技术问题 Extra ChatGPT

Objective-C ARC: strong vs retain and weak vs assign

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?

There are three new memory management attributes for properties introduced by ARC strong, weak and unsafe_unretained.
@NJones There are two property attributes (weak and strong) and 4 variable lifetime qualifiers (__strong, __weak, __unsafe_unretained, __autoreleasing). See the ARC Notes below.
@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:"

C
Community

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;

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;
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)
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)
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 nil
@RDC, What does default mean? If I use @property (nonatomic) NSString *string it is strong? Or assign? Because both are defaults.
D
David Ravetti

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.


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.
assign compiles just fine for me in ARC projects with deployment target 4.0.
@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 weak
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. stackoverflow.com/questions/7796476/…
@JeremyP Yes, your answer is spot-on. I was reacting to @Mattia. I was pointing out that assign is still valid in some cases.
V
Vadoff

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


@Sakthimuthiah is right, you must to correct your answer.
@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: stackoverflow.com/questions/12347236/…
T
Tricertops

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.


M
Mingming

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.


M
Mahadev Mandale

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.


N
Nikunj Patel

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;


C
Chen Rui

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