Reference-counting memory management remains unchanged in the arc. In arc, there are two methods: Valid and invalid. We can use them together in an app.
Use clang (LLVM compiler) or a later version, and specify the "-fobjc-arc" compiler attribute to use arc;
In oc, the way to think about counting-type memory management is to think about the changes caused by arc:1. Self-generated objects are held by yourself. 2. Non-self-generated objects can be held by themselves. 3. Release your own objects when they are no longer needed. 4. objects not owned by the user cannot be released.
Ownership modifier: In oc, to process objects, you can define the variable type as id type or various object types. The object type is a pointer to an oc class like NSObject. The id type is used to hide the Class Name of the object type, which is equivalent to void * in c. In arc, a modifier is required: _ strong _ weak _ unsafe_unretained _ autoreleasing.
1. _ strong is the default ownership modifier of the id type and object type. That is to say, the id variable in the Code is actually appended with the ownership modifier. When the ownership modifier is not explicitly specified for the id and object type, the default value is strong: id obj = [NSObject alloc] init]; id _ strong obj = [[NSObject alloc] init]; The above two lines of code are equivalent.
Non-arc comparison:
{ id __strong obj = [[NSObject alloc] init];}{ id obj = [[NSObejct alloc] init]; [obj release];}
Code for calling the release method is added to release generated and held objects.
The _ strong modifier indicates a "strong reference" to an object. Variables with strong references are discarded when they exceed the scope. When a strong reference fails, the referenced object is released. To analyze the code: Get the object you own. {// Self-generated and holding Object id _ strong obj = [[NSObject alloc] init]; // because the variable obj is strongly referenced, the object is held by the user.} // because the variable obj is out of its scope and the strong reference is invalid, the object held by the user is automatically released, the object does not exist in multiple regions, so the object is discarded.
Get objects not owned by yourself: {// get the id _ strong obj = [NSMutableArray array] of objects not generated and held by yourself; // because the variable obj is strongly referenced, so I own the object} // because the variable obj is out of its scope, the strong reference is invalid. // Automatically release the object you hold.
Here, the owner of the object and the lifecycle of the object are also clear. Variables of the _ strong modifier can be assigned values to each other. The _ strong modifier can manage the owner of an object not only in the scope of the variable, but also in the assignment.
In oc, we can use variables with the _ strong modifier.
@interface Test: NSObject { id __strong obj_;}- (void)setObject:(id __strong)obj;@end
With the _ strong modifier, you no longer need to type retain or release. They perfectly meet the "reference counting memory management thinking method": 1. Self-generated objects, held by themselves. 2. Non-self-generated objects can be held by themselves. 3. release an object that you no longer need. 4. objects not owned by the user cannot be released.
Among them, 1 and 2 can be completed by assigning values to variables with the _ strong modifier. You can discard any variable with the _ strong modifier or assign a value to the variable: "you no longer need to release your own objects."
The fourth item is not the release of the object we own. because we do not need to type release again, it will not be executed originally. They are all satisfied with the reference counting memory management thinking method.
_ Strong is the default modifier, so we do not need to type it. Arc's effective and simple programming follows the way of thinking about oc memory management.
2. _ weak: cyclic reference is generated during reference counting.
Let's look at the circular reference code:
@ Interface Text: NSObject {id _ strong obj _;}-(void) setObject :( id _ strong) obj; @ end @ implementation Text-(id) init {self = [super init]; return self;}-(void) setObject :( id _ strong) obj {obj _ = obj ;} @ end {id text0 = [[Text alloc] init]; // object a id text1 = [[Text alloc] init]; // object B [text0 setObject: text1]; // The obj _ of object a holds the strong reference of object B. In this case, the strong reference variables of object B are obj _ and text1. [text1 setObject: text0] of object a. // The object held by obj _ of object B Strong reference of a. In this case, the strong reference variables of object B are obj _ and text0} of object B. // The strong reference is invalid because the text0 variable is out of scope. Automatically release object
// Because the text1 variable is out of scope, the strong reference is invalid, automatically release object B // In this case, the strongly referenced variable holding object a is obj _ of object B, and the strongly referenced variable holding object B is obj _ of object a, causing memory leakage.
In addition, when you only have one object and the object holds its own, it will also be leaked.
_ Weak is opposite to strong. It provides weak references and cannot hold object instances. In order not to save the generated and held objects in their own State, the generated objects are immediately released. {Id _ strong obj1 = [[NSObject alloc] init]; id _ weak obj2 = obj1 ;}
The _ weak modifier does not hold objects. Therefore, when the variable scope is exceeded, the object is released. If you change the class member variables that may have been referenced cyclically to a member variable with _ weak modification as follows, loop reference will be avoided. @ Interface Text: NSObject {id _ weak obj _;}-(void) setObject :( id _ strong) obj; @ end
_ Weak has another advantage: When holding a weak reference of an object, if the object is discarded, the weak reference will automatically become invalid, and is in the state where nil is assigned a value (null weak application ).
In ios5 and later versions, _ weak is used, while in ios4, the _ unsafe_unretained modifier is used.
3. _ unsafe_unretained is an insecure ownership modifier. Variables with the _ unsafe_unretained modifier do not belong to the compiler memory management object. Like _ weak, because the objects generated and held by the user cannot be owned by the user, the generated objects will be released immediately. Code:
Id _ unsafe_unretianed obj1 = nil; {id _ strong obj0 = [[NSObject alloc] init]; // obj0 indicates a strong reference. Own object obj1 = obj0; // The obj1 variable does not hold strong references of objects or weak references .} // The obj0 is out of scope and the strong reference is invalid. You can release your own objects because they do not have owners. // The object represented by the obj1 variable has been deprecated and the suspension pointer.
4. When the _ autoreleasing modifier is valid for arc, autorelease and NSAID utoreleasepool cannot be used directly. We should write it as: @ autoreleasepool {id _ autoreleasing obj = [[NSObject alloc] init];
} @ Autoreleasepool to replace the generation, hold, and discard of the NSAID utoreleasepool class object. When the arc is valid, the autorelease method should be called by assigning values to variables with the _ autoreleasing modifier.
@ Autoreleasepool {// obtain the Object id _ strong obj = [NSMutableArray array] that is not generated and held by the user; // because the variable obj is a strong reference, you own the object, after the compiler determines the method name of the object, the object is automatically registered to autoreleasepool} // because the variable obj is out of scope, the strong reference is invalid, and the Held Object is automatically released, with the completion of @ autoreleasepool, all objects registered to it are released. Because the object owner does not exist, it is discarded.
There is also the variable modified by _ weak. When accessed, it will certainly access the object registered to autoreleasepool, because the _ weak modifier only holds the weak reference of the object, however, this object may be discarded during access to the referenced object. If you register an object to the autoreleasepool, you can ensure that the object exists before the autoreleasepool block ends;
For example, _ autoreleasing is as follows: NSError ** error is equivalent to: NSError * _ autoreleasing * error.
An error occurs as follows:
NSError * error = nil; NSError ** pError = & error; Add the _ strong modifier to the modification. NSError * error = nil; NSError * _ strong * pError = & error; NSError _ weak * error = nil; NSError * _ weak * pError = & error; the following example is also true: NSError _ strong * error = nil; NSError ** pError = & error; in fact, it is rewritten: NSError _ strong * error = nil; NSError _ autoreleasing * tem = error; NSError ** pError = & tem;
In the NSAID utoreleasepool, it can be nested and used in @ autoreleasepool:
@autoreleasepool{ @autoreleasepool{ @autoreleasepool{ id __autoreleasing obj = [[NSObject alloc] init]; } }}
Whether in arc or non-arc, we can use the non-public function used for debugging: _ objc_autoreleasePoolPrint. It can help us debug the objects registered to the autoreleasepool effectively.
The variables of _ strong and _ weak modifiers are similar to the functional pointers std: shared_ptr and std: weak_ptr in c ++. Shared_ptr holds c ++ class instances by reference counting. weak_ptr can avoid circular reference. We strongly recommend these two pointers when you have to use c ++ without the _ strong and _ weak modifiers.
New ARC rules: 1. You cannot use retain/release/retainCount/autorelease 2. You cannot use NSAllocateObject/NSDeallocateObject 3. You must follow the naming rules for memory management. 4. Do not explicitly call dealloc 5. Use @ orauteleasepool block instead of nutoreleasepool 6, cannot use area NSZone 7, object type variables cannot be members of C language struct 8, explicit conversion id and void *
"You do not need to type retain and release code again when setting the arc to be valid," the official documentation said ."
I do not know whether the alloc implementation is mentioned. In gnustep, alloc is implemented by calling NSAllocateObject. In fact, he is the same as retain, which will cause errors in the arc state. The same applies to NSDeallocateObject.
Object variables cannot be a member of the C language struct: What does this mean? Because the C language cannot manage the lifecycle of struct members. While arc has handed over the memory management to the compiler, so the compiler must know and manage the object lifecycle. Therefore, it cannot be a struct member. If you want to add the object type variable to the struct, You Need To forcibly convert it to void * or add the _ unsafe_unretained modifier.
Explicitly convert id and void * for simple Value assignment: Use _ bridge to convert id obj = ------ void * p = (_ bridge void *) obj; id o = (_ bridge id) p; this assignment has a disadvantage, that is, security issues. It is more secure than _ unsafe_unretained. If you do not pay attention to object management, it is easy to cause memory leakage.
_ Bridge has two types: __bridge_retianed and _ bridge_transfer. They are similar to retian and release; void * p = 0; {id obj = [[NSObject alloc] init]; p = (_ bridge_retained void *) obj ;}
// At this time, the scope ends and obj is released. However, the _ bridge_retianed conversion makes the Variable p look at and hold the object. Therefore, the object will not be discarded.
Id obj = (_ bridge_transfer id) p; // object held by ob, p is released.
When writing code, when the arc is valid, the attributes of the oc class also change. For example, @ property (nonatomic, strong) NSString * name; the attribute list is as follows:
In the copy attribute above, the value assignment is to copy the object generated by the value assignment source through the NSCopying interface and the copyWithZone method. Nonatomic here is used to explain that multi-thread is prohibited and variable protection can be implemented to improve efficiency. There is also a atomic which is the thread protection mechanism of oc to prevent reading when information is not written.
Here we have to talk about memory allocation: NSObject * _ strong * array = nil;
Allocation: array = (id _ strong *) calloc (***, sizeof (id); here is the allocated *** memory block, because we use the _ strong modifier, we must first initialize it to nil; calloc will initialize your region to 0;
But what if we use malloc? Array = (id _ strong *) malloc (sizeof (id) *****); there is no initialization, that is, the memory is allocated randomly. If you initialize it like this: for (NSInteger I = 0; I <***; ++ I) {array [I] = nil;} is dangerous, because we are a strongly referenced object, when you assign a value to nil, the objects held by array [I] will be released, but the objects are randomly assigned addresses at this time, it is meaningless, that is, we have released a non-existent object. In this case, we need to use memset for initialization. Memset (array, 0, ***** sizeof (id ));
Implementation of ARC: 1. _ strong optimization problem. Id _ strong obj = [NSMutableArray array]; The simulated code in the compiler is as follows: id obj = objc_msgSend (NSMutableArray, @ selector (array); objc_retainorauteleasedvalue (obj ); objc_release (obj); here is a function named objc_retainAutoreleasedValue. There is also a function objc_autoreleasepoolReturnValue.
Let's take a look at the conversion of the array Function: + (id) array {return [[NSMutableArray alloc] init];} the conversion simulation code: id obj = objc_msgSend (NSMutableArray, @ selector (alloc); objc_msgSend (obj, @ selector (init); return objc_autoreleaseReturnValue (obj );
The objc_autoreleaseReturnValue function returns the registered object to autoreleasepool. Objc_autoreleaseReturnValue checks the list of execution commands of the method or function caller using this function. If the method or function caller calls a method or function, the objc_retainAutorelwasedReturnValue function is called immediately, the returned object will not be registered to the autoreleasepool, but will be passed directly to the method or function caller. Collaboration:
2. _ weak 1). If the object referenced by the variable with the _ weak modifier is discarded, nil is assigned to the variable. 2) If the variable with the _ weak modifier is used, it is the object registered to autoreleasepool.
Id _ weak obj1 = obj; what did he do? Let's see: id obj1; objc_initWeak (& obj, obj); objc_destroyWeak (& obj1); here is the process of initialization and termination. Actually, it is like this: id obj1; obj1 = 0; objc_storeWeak (& obj1, obj); objc_storeWeak (& obj1, 0); explain: here, the first storeWeak function uses the address of the value assignment object of the second parameter as the key value, and registers the address of the variable with the _ weak modifier of the first parameter to the weak table. It can be noted that the second parameter is 0 during the second call, that is, when the second parameter is-0, the address of the variable will be deleted from the weak table.
What is the weak table? In this case, we think of reference counting tables. They all use hash. Here, a key value can register the addresses of multiple variables. Just like an object, you can pay multiple variables with the _ weak modifier at the same time. That is to say, if you use the address of an obsolete object as the key value for retrieval, you can tell to get the address of the variable with the _ weak modifier.
When an object is released, no one is held out of the object, and action will appear in the program in the future: 1. objc_release 2. Because the reference count is 0, therefore, the function that executes the sixth step of dealloc 3, _ objc_rootDealloc 4, object_dispose 5, objc_destructInstance 6, and objc_clear_deallocating will take the following action: 1. Obtain the record from the weak table that the address of the discarded object is a key value. 2. assign a value of nil to all addresses with the _ weak modifier variable in the record. 3. Delete the record from the weak table. 4. delete records with the obsolete object address as the key value from the reference counter table.
When we use an object registered to autoreleasepool: id _ weak obj1 = obj; the simulation code is: id obj1; objc_initWeak (& obj1, obj ); id tmp = objc_loadWeakRetained (& obj1); objc_autorelease (tmp); objc_destroyWeak (& obj1 );
The objc_loadWeakRetained and objc_autorelease calls are added here. 1. objc_loadWeakRetained: The function retrieves the object referenced by the _ weak modifier and retain. 2. The objc_autorelease function registers the object to the autoreleasepool.
In this way, you can safely use variables with the _ weak modifier. But what if there are many objects? The best way is to temporarily assign a value to the variable with the _ strong modifier. In this way, the object is only logged on to autoreleasepool once.
The last note is: id _ weak obj = [[NSObject alloc] init]; and id _ unsafe_unretained obj = [[NSObject alloc] init]; this is not acceptable, the former is because the object cannot be held, and the latter is the suspension pointer assigned by obj. Although it will not cause memory leakage in arc, it is better not to use it like this.
3. The reference count function for obtaining the reference count value: uintptr_t _ objc_rootRetainCount (id obj). This function can obtain the reference count value of a specified object (retainCount is no longer available in ARC ); function _ objc_autoreleasePoolPrint will observe the reference object registered to autoreleasepool.
----- 2014/3/18 Beijing