The difference between copy, strong, retain, weak and assign in iOS

Logic diagram:

The difference between copy, strong, retain, weak and assign in iOS
article logic diagram

Before we know the difference between them, we must first know what operations the assignment of the NSObject object does.

In fact, A=C is created in memory of a A, and then opened up a memory B, B inside the stored value C.

The difference between copy, strong, retain, weak and assign in iOS
NSObject assignment Figure 1

As follows:

NSMutableString*tempMStr [[NSMutableString alloc]initWithString:@ = "strValue"]; NSLog (@ tempMStr address:%p, tempMStr value tempMStr value reference count%@//n% @, "tempMStr, tempMStr, [tempMStr, valueForKey:@" retainCount "]); / / output value of tempMStr address: 0x7a05f650, tempMStr value strValue, tempMStr value of the reference count of 1

Here tempMStr is A, the value of the address is C, “strValue” is B, and the application of this concept is to count C, assigned to another variable or pointer is set to nil, such as tempStr = nil, will make the reference count is increased or decreased. When the memory area reference count is 0, the data will be erased. And we use copy, strong, retain, weak, assign difference in:

1 whether to open up new memory
if there is an increase in the number of references to address C

It should be noted that the property modifier is used when it is assigned.

1 typical NSMutableString as an example

@property (copy, nonatomic) NSMutableString*aCopyMStr; @property (strong, nonatomic) NSMutableString*strongMStr; @property (weak, nonatomic) NSMutableString*weakMStr (assign, nonatomic); @property NSMutableString*assignMStr; NSMutableString*mstrOrigin [[NSMutableStringalloc]initWithString:@ = "mstrOriginValue"]; self.aCopyMStr= mstrOrigin; self.strongMStr= mstrOrigin; self.strongMStr= mstrOrigin; self.weakMStr= mstrOrigin; NSLog (@ mstrOrigin output:%p,%@// n mstrOrigin, mstrOrigin, NSLog (@ aCopyMStr); output:%p,%@//n, _aCopyMStr, _aCopyMStr); NSLog (@ strongMStr output:%p,%@//n, _strongMStr, _strongMStr); NSLog (@ weakMStr output:%p,%@//n, _weakMStr, _weakMStr); NSLog ("refcounted% @ @" [mstrOriginvalueForKey:@ "retainCount"]); / / output //2016-09-01 15:1 9:13.134 lbCopy[1205:87583] mstrOrigin mstrOriginValue //2016-09-01 15:19:13.135 output: 0x7892a5e0, lbCopy[1205:87583] aCopyMStr 0x7893deb0, mstrOriginValue //2016-09-01 15:19:13.135 output: lbCopy[1205:87583] output: 0x7892a5e0, mstrOriginValue //2016-09-01 strongMStr 15:19:13.135 lbCopy[1205:87583] weakMStr 0x7892a5e0 mstrOriginValue //2016-09-01 15:19:13.135, output: lbCopy[1205:87583] reference count 2

The strongMStr memory address and the pointer to the weakMStr and mstrOrigin are the same, but the mstrOrigin memory reference count is 2, not 3, because although weakMStr points to the data memory address (after C, see Figure 1), but does not increase the count of C. Copy modified aCopyMStr, after the assignment is to open up a separate memory, memory to save the “mstrOrigin” string, and point.

The schematic of the copy is as follows:

The difference between copy, strong, retain, weak and assign in iOS
NSMutableString copy schematic 2

Visible when I modify the value of mstrOrigin, it will not affect the aCopyMStr, will only affect the strongMStr and weakMStr. Let’s verify

NSLog (@ C to modify the original value ------------------------ "); [mstrOriginappendString:@" 1 "]; NSLog (@ mstrOrigin output:%p,%@//n, mstrOrigin, mstrOrigin); NSLog (@ aCopyMStr output:%p,%@//n, _aCopyMStr, _aCopyMStr); NSLog (@ strongMStr output:%p,%@//n." _strongMStr, _strongMStr); NSLog (@ weakMStr output:%p,%@//n, _weakMStr, _weakMStr); / / //2016-09-01 15:33:02.839 lbCopy[1205:87583] output mstrOrigin output: 0x7892a5e0, mstrOrigin1 //2016-09-01 15:33:02.839 lbCopy[1205:87583] aCopyMStr mstrOrigin //2016-09-01 15:33:02.839 output: 0x7893deb0, lbCopy[1205:87583] strongMStr 0x7892a5e0, mstrOrigin1 //2016-09-01 15:33:02.839 output: lbCopy[1205:87583] weakMStr output: 0x7892a5e0, mstrOrigin1

Copy will re create new memory to save the same data. The assigned object and the original value changes do not affect each other. Strong and weak are assigned to the original value of the data address, the difference is that the former will be a reference to the data address count +1, the latter will not

Is there any real difference between the reference counts and the +1?

If you know that the reference value of the value address is 0, the value on the address will be released”. Then the difference is not difficult to understand, weak modified A is a pointer to the value of the C address, then the address for other point when released his pointer, the value of the address reference count becomes 0, the value of A is nil. In other words, there is no other strong reference pointer modifier on the address C C will be released immediately, the value of A becomes nil.

Here we have to initialize mstrOrigin and set strongMStr to nil to C the reference count is 0, then the output of weakMStr, to see whether the nil.
note: initialization and can be set to nil pointer address data reference count by 1

MstrOrigin [[NSMutableStringalloc]initWithString:@ = "mstrOriginChange2"]; self.strongMStr=nil; NSLog (@ mstrOrigin output:%p,%@//n, mstrOrigin, mstrOrigin); NSLog (@ strongMStr output:%p,%@//n, _strongMStr, _strongMStr); NSLog (@ weakMStr output:%p,%@//n, _weakMStr, _weakMStr); the output of //2016-09-01 15:41:33.793 lbCopy[1247:100742] mstrOrigin 0x7874d140 mstrOriginChange2 //2016-09-01 15:41:33.793, output: lbCopy[1247:100742] output: 0x0, strongMStr (null) //2016-09-01 15:41:33.794 lbCopy[1247:100742] weakMStr output: 0x0, (null)

Visible reference count 2 is added to mstrOrigin and strongMStr.
conclusion: copy will reopen new memory to save the same data. The assigned object and the original value changes do not affect each other. Strong and weak are pointing to the original data address, change of storng and weak will modify the original value. The difference is that the former will count the data address +1 to prevent the original address value is released, but the latter will not, when other values are not in the value of the address, the value of the address is released, the value of weak is nil. We say that we will increase the reference count to a strong reference to the data address, without changing the reference count as a weak reference

1.2 the difference between assign and weak

The value of assign and weak modification is assigned, and the pointer structure address and value are output

Self.assignMStr= mstrOrigin; self.weakMStr= mstrOrigin; mstrOrigin [[NSMutableStringalloc]initWithString:@ = "mstrOriginChange3"]; NSLog (@ weakMStr output:%p,%@//n, _weakMStr, _weakMStr); NSLog (@ assignMStr output:%p,%@//n, self.assignMStr, self.assignMStr);

Can be found in the output assignMStr will occasionally occur when the collapse of the situation. The reason is to send a wild pointer. Assign and weak, pointing to the C and the count is not +1, but when the C address reference count is 0, assign will not address the C address of the B data erase operation, but the value of the release. This leads to the existence of the wild pointer, that is, when the address has not yet written on other values, the output of the normal value, but once the data is written down, the pointer may not have a value at any time, resulting in collapse.

1.3 what is retain

ARC is the key to the attribute constructor before retain, copy, assign, strong, and weak are the keywords that ARC comes with.
retain is now the same as strong, which is the pointer to the value of the address, while the reference count plus 1.

2 non NSMutableString case

above we discuss a typical example of NSMutableString, that is, non container variable. That is to say, there are three other types that need to be discussed…

1 non container variable NSSting
2 container variable variable NSMutableArray
3 container immutable variable NSArray

What’s more important is that different types have different results… Well, don’t run away, we’ve talked about 1/4 for a while, and then we’re going to talk about other 3/4 scenarios. But the good news is that several other situations are basically similar to the above non container variable.

2.1 container variable

A typical example of variable variable container is NSMutableArray
the following code can be ignored, only for reference

@property (copy, nonatomic) NSMutableArray*aCopyMArr; @property (strong, nonatomic) NSMutableArray*strongMArr; @property (weak, nonatomic) NSMutableArray*weakMArr; NSMutableArray*mArrOrigin = [[NSMutableArrayalloc]init]; NSMutableString* mstr1 [[NSMutableStringalloc]initWithString:@ = "value1"]; NSMutableString*mstr2 = [[NSMutableStringalloc]initWithString:@; NSMutableString*mstr3 = "Value2" [[NSMutableStringalloc]initWithString:@ "value3"]; [mArrOriginaddObject:mstr1]; [mArrOriginaddObject:mstr2]; / / mArrOrigin copy to the aCopyMArr. StrongMArr, weakMArr self.aCopyMArr= mArrOrigin; self.strongMArr= mArrOrigin; self.weakMArr= mArrOrigin; NSLog (@ mArrOrigin output:%p,%@//n, mArrOrigin, mArrOrigin); NSLog (@ aCopyMArr output:%p,%@//n, _aCopyMArr, _aCopy MArr NSLog (@ strongMArr); output:%p,%@//n, _strongMArr, _strongMArr); NSLog (@ weakMArr output:%p,%@//n, _weakMArr, _weakMArr); NSLog (@ weakMArr output:%p,%@//n, _weakMArr[0], _weakMArr[0]); NSLog (@ mArrOrigin data reference count "[mArrOriginvalueForKey:@"% @ retainCount "]); NSLog ("%p%p%p @%p, & mArrOrigin, mArrOrigin, mArrOrigin[0], mArrOrigin[1]); / / 2016-09-02 20:42:30.777 lbCopy[4207:475091] mArrOrigin is the following output output: 0x78f81680, (value1, Value2) 2016-09-02 20:42:30.777 lbCopy[4207:475091] aCopyMArr output: 0x7a041340, (value1, Value2) 2016-09-02 20:42:30.777 lbCopy[4207:475091] output: 0x78f81680, strongMArr (value1, Value2) 2016-09-02 20:42:30.777 lbCopy[4207:475091] weakMArr output: 0x78f81680, (value1, Value2) 2016-09-02 20:42:30 .777 lbCopy[4207:475091]: 0x78f816a0, weakMArr output reference count value1 2016-09-02 20:42:30.778 lbCopy[4207:475091] mArrOrigin data (3, 3) 2016-09-02 20:42:30.778 lbCopy[4207:475091] 0xbffb4098 0x78f81680 0x78f816a0 0x78f81710 / / / / output is above add a [mArrOriginaddObject:mstr3] element to the original array; NSLog (@ mArrOrigin output:%p,%@//n, mArrOrigin, mArrOrigin); NSLog (@ "aCopyMArr output:%p,%@//n, _aCopyMArr, _aCopyMArr); NSLog (@ strongMArr output:% P,%@//n, _strongMArr, _strongMArr); NSLog (@ weakMArr output:%p,%@//n, _weakMArr, _weakMArr); NSLog (@ mArrOrigin data in the reference count,% @" [mArrOriginvalueForKey:@ "retainCount"]); / / modify the original elements in the array, to see whether there is a change of [mstr1appendFormat:@ "AAA"]; NSLog (@ mArrOrigin output: %p,%@//n, mArrOrigin, mArrOrigin); NSLog (@ aCopyMArr output:%p,%@//n, _aCopyMArr, _aCopyMArr); NSLog (@ strongMArr output:%p,%@//n, _strongMArr, _strongMArr); NSLog (@ weakMArr output:%p,%@//n, _weakMArr, _weakMArr); / / the following is the output of 2016-09-02 20:42:30.778 lbCopy[4207:475091] mArrOrigin output: 0x78f81680, (value1, Value2, value3) 2016-09-02 20:42:30.778 lbCopy[4207:475091] aCopyMArr output: 0x7a041340, (value1, Value2) 2016-09-02 20:42:30.778 lbCopy[4207:475091] strongMArr output: 0x78f81680, (value1, Value2, value3) 2016-09-02 20:42:30.778 lbCopy[4207:475091] weakMArr output: 0x78f81680, (value1, Value2, value3) 2016-09-02 20:42:30.779 lbCopy[reference count 4207:475091] data in mArrOrigin (3, 3, 2) 2016-09-02 20:42:30.779 lbCopy[4207:475091] M Output: 0x78f81680, ArrOrigin (value1aaa, Value2, value3) 2016-09-02 20:42:30.779 lbCopy[4207:475091] aCopyMArr output: 0x7a041340, (value1aaa, Value2) 2016-09-02 20:42:30.779 lbCopy[4207:475091] strongMArr output: 0x78f81680, (value1aaa, Value2, value3) 2016-09-02 20:42:30.779 lbCopy[4207:475091] weakMArr input / output: 0x78f81680, (value1aaa, Value2, value3) / / output is more than

The above code a little more, the operation is mArrOrigin (value1, Value2) assigned to copy, strong, weak modified aCopyMArr, strongMArr, weakMArr. By adding elements to the original array, modify the original array element values, and then output the mArrOrigin reference count, and array address, view changes.
found that the array itself points to the memory address in addition to the aCopyMArr re opened an address, strongMArr, weakMArr and mArrOrigin pointer to the address is the same. In other words

The container variables are the same as the container and the container variable, copy deep copy, strongMArr, weakMArr and assign are shallow copy

In addition, we find that the data reference count in the copied object mArrOrigin is not 1 but 3. That is to say, the data copy in the container is a shallow copy. At the same time, when we modify the data in an array, the data in strongMArr, weakMArr, and aCopyMArr are changed

The data in the container variable is a shallow copy

Copy structure of container variable

The difference between copy, strong, retain, weak and assign in iOS
NSMutableArray copy schematic 3

2.2 non container invariant variable

Typical example is NSString

We still use the code to produce results

@property (copy, nonatomic) NSString*aCopyStr; @property (strong, nonatomic) NSString*strongStr; @property (weak, nonatomic) NSString*weakStr; @property (assign, nonatomic) NSString*assignStr; NSLog (@ "//n//n//n//n------------------ can not ------------------------ experimental variables"); NSString*strOrigin = "[[NSStringalloc]initWithUTF8String: string 1"]; self.aCopyStr= strOrigin; self.strongStr= strOrigin; self.weakStr= strOrigin; NSLog (@ strOrigin output:%p,%@//n, strOrigin, strOrigin); NSLog (@ aCopyStr output:%p,%@//n, _aCopyStr, _aCopyStr); NSLog (@ strongStr output:%p,%@//n, _strongStr, _strongStr); NSLog (@ weakStr output:%p,%@//n, _weakStr. _weakStr (NSLog); @ C modified after the original value ------------------------ "); strOrigin [email protected]" AAA "; NSLog (@ strOrig In output:%p,%@//n, strOrigin, strOrigin); NSLog (@ aCopyStr output:%p,%@//n, _aCopyStr, _aCopyStr); NSLog (@ strongStr output:%p,%@//n, _strongStr, _strongStr); NSLog (@ weakStr output:%p,%@//n, _weakStr, _weakStr); NSLog (@ "C" conclusion ------------------------); NSLog (@ "strOrigin value for change, but strOrigin and aCopyStr have been changed to address and description, immutable value types can not be modified, re initialization"); self.aCopyStr=nil; self.strongStr=nil; NSLog (@ strOrigin output:%p,%@//n, strOrigin strOrigin, NSLog (@ aCopyStr); "output:%p,%@//n, _aCopyStr, _aCopyStr); NSLog (@ strongStr output:%p,%@//n, _strongStr, _strongStr); NSLog (@ weakStr output:%p,%@//n, _weakStr, _weakStr); NSLog (@ C" conclusion ------------------- - "); NSLog (@" when only weakStr with C, the value will still be released with non container variable variable "); / / the following is not a variable output C experimental ------------------------ 2016-09-02 21:08:44.053 lbCopy[4297:488549] strOrigin string 1 2016-09-02 output: 0x7a2550d0, 21:08:44.053 lbCopy[4297:488549] aCopyStr string 1 2016-09-02 output: 0x7a2550d0, 21:08:44.054 lbCopy[4297:488549] strongStr output 0x7a2550d0, string 1 2016-09-02 21:08:44.054 lbCopy[4297:488549] weakStr string 1 2016-09-02 output: 0x7a2550d0, 21:08:44.054 lbCopy[4297:488549] strOrigin 21:08:44.054 lbCopy[4297:488549] 2016-09-02 memory reference count 3 C 2016-09-02 21:08:44.054 lbCopy[4297:488549] modified value ------------------------ strOrigin output: 0x8c1f 8, AAA 2016-09-02 21:08:44.054 lbCopy[4297:488549] aCopyStr string 1 2016-09-02 output: 0x7a2550d0, 21:08:44.054 lbCopy[4297:488549] strongStr string 1 2016-09-02 output: 0x7a2550d0, 21:08:44.055 lbCopy[4297:488549] weakStr string 1 2016-09-02 output: 0x7a2550d0, 21:08:44.055 lbCopy[4297:488549] 2016-09-02 21:08:44.055 lbCopy[4297:488549] strOrigin ------------------------ conclusion C values for change, but strOrigin and aCopyStr have been changed to address and description, immutable type the value can not be modified, re initialization of 2016-09-02 output: 0x8c1f8, 21:08:44.059 lbCopy[4297:488549] strOrigin AAA 2016-09-02 21:08:44.059 lbCopy[4297:488549] aCopyStr output: 0x0, (null) 2016-09-02 21:08:44.060 lbCopy[4297:488549] strongStr output: 0x0, (null) 2016-09-02 21:08:44.060 lbCopy[4297:488549] weakStr output: 0x0, (null) 2016-09-02 21:08:44.060 lbCopy[4297:488549] 2016-09-02 21:08:44.061 lbCopy[4297:488549] ------------------------ C conclusion when only weakStr has a C value, will still be released with non variable variable output is above / / container

Here we copy strOrigin to aCopyStr, strongStr, weakStr, and then output their value address, found that they are the same as the four value of the address, and the strOrigin value of the reference count is 3. Modify the strOrigin and found that the value of the strOrigin address change, the other three value address unchanged, will be aCopyStr, strongStr set to nil, found weakStr followed by nil.

Synthesis of the above phenomenon NSString and NSMutableString (non container variable) is basically the same, in addition to copy, NSString is a shallow copy, NSMutableString is a deep copy. So why NSString’s copy is a shallow copy, that is why aCopyStr does not open up a separate memory out of it. The answer is simple, because the value of the variable will not change, since it will not change, so there is no need to re open a memory out of the aCopyStr to point to him, directly to the original value of the position can be. Schematic diagram is as follows

The difference between copy, strong, retain, weak and assign in iOS
NSString copy schematic 4

Therefore, the container is not variable except for the other characteristics of copy and the non container variable, copy is a shallow copy

2.3 immutable container variables

Typical object NSArray. The object experiment. But the conclusion here is not in fact, experiments can also probably know the probability of
in variable container variables, the container itself is a shallow copy including copy, with the NSString container in which the data are shallow, with NSMutableArray.

3 summarize the differences between
copy, strong, weak, assign.

Variable variable, copy is re opened a memory, strong, weak, assgin after the three do not open up memory, only the original pointer to save the value of the memory location, pointing to the storng after the memory reference count +1, and weak, not assgin. Weak, assgin in the reference value of the memory reference count is 0 when the value is null, and weak will be the memory value is set to nil, not assign, assign has not been rewritten before can be output in memory, but once rewriting will appear collapse

Immutable variables, because the value itself can not be changed, copy is not necessary to open up a memory store and the original memory of the same value, so the default memory management system is a shallow copy. Other variables, such as weak variables, will also change to nil when the memory reference count is 0.

The container itself follows the above guidelines, but each value in the container is a shallow copy.

To sum up, when creating the property constructor to create a variable value1, the use of copy, strong, weak, assign according to the specific use of the decision. Value1 = Value2, if you want to modify the value1 and Value2 will not affect each other with the use of copy, or strong, weak, assign. If you also hope that the original value of C (C is what see Figure 1) for nil, your variables are not nil with strong, instead of using weak and assign. Weak and assign ensure that a strong reference to a memory, such as delegate, we use weak, is to prevent the generation of circular references.
in addition, we discussed the class variables, the direct creation of local variables is the default Strong modifier

Why delegate use weak or assign instead of strong

A create object B, B has C class object C, so a has a reference to B, B has a reference to the C, A.B reference counts were 1, 1. When c.delegate = B, in fact, there is a reference to the B, if the C delegate at this time will be modified with strong will be the value of the B memory reference count +1, B reference count is 2. When the end of the life cycle of a, along with the release of B B reference, the reference count to 1, resulting in B can not be released, B cannot release and lead to B reference to the C C cannot release the reference count is 1, thus B and C remained in the memory.

To solve this problem is to use the weak or assign modified delegate, although there will be C there will still be a reference to the B, but the reference is a weak reference, when the end of the life cycle of a B, the reference count is 0, the release of B after C reference disappeared, C reference count is 0 release.

Project address https://github.com/ai966669/copy

AC qq:578172874

Wrong hope I can help out, O (a _ U) O.