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

后端 未结 8 2218
眼角桃花
眼角桃花 2020-11-22 15:59

There are two new memory management attributes for properties introduced by ARC, strong and weak.

Apart from copy, which is ob

相关标签:
8条回答
  • 2020-11-22 16:01

    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
    0 讨论(0)
  • 2020-11-22 16:02

    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.

    0 讨论(0)
  • 2020-11-22 16:03

    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.

    0 讨论(0)
  • 2020-11-22 16:06

    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;

    0 讨论(0)
  • 2020-11-22 16:09

    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.

    0 讨论(0)
  • 2020-11-22 16:12

    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
    0 讨论(0)
提交回复
热议问题