Basic Principles of Memory Management
The basic principles of memory management are as follows:
The self-generated object is the owner
An object generated by yourself can also be its owner (an object can be held by multiple people)
If you do not want to hold an object, you must release its ownership.
Objects that no longer hold ownership cannot be released.
This principle always exists no matter whether the ARC works or not.
Ownership keywords
From the code point of view, the difference between code with and without ARC lies in the following keywords.
Similar to the object type of NSObject *, or id type 1, when the ARC is valid, these keywords must use 2 according to the specific situation.
_ Strong
_ Weak
_ Unsafe_unretained
_ Autoreleasing
_ Strong is the default modifier.
_ Weak modifies the weak reference of an automatic nil.
_ Unsafe_unretained declares a weak reference that will not automatically nil. When the variable is released, it becomes a wild pointer.
_ Autoreleasing is used to modify the parameter of a function declared as (id *). It is released when the return value of the function is returned.
Next, let's take a look at some technical details after using the ARC Based on the following ARC usage guidelines.
ARC usage guidelines
In order to be inferior to the second program, when the ARC is effective, our code must follow the following guidelines.
You cannot use retain/release/retainCount/autorelease
NSAllocateObject/NSDeallocateObject cannot be used
NSZone cannot be used
You cannot explicitly call dealloc.
Memory management-related functions must follow naming rules
Use @ autoreleasepool instead of NSAID utoreleasepool
The Objective-C object cannot be a member of the C language struct (struct/union ).
Cast must be specified between [id] and [void *].
We recommend that you use the Objective-C class to manage the data format, instead of the struct in the C language. You cannot implicitly convert id and void *.
Let's analyze them one by one
You cannot use retain/release/retainCount/autorelease
The memory management is completely done by the compiler, so the previously memory-related functions (retain/release/retainCount/autorelease) cannot appear in the program. The following is also described in Apple's ARC document.
After the ARC is valid, you do not need to use retain and release again.
If we use these functions in the program, the compilation error message similar to the following is obtained.
Error: ARC forbids explicit message send of 'release'
[O release];
^ ~~~~~~~ NSAllocateObject/NSDeallocateObject cannot be used
When generating and holding an Objective-C object, the alloc interface function of NSObject is often used as follows.
Id obj = [NSObject alloc]; in fact, if we read the code about alloc in GNUstep, we will understand that it actually uses NSAllocateObject to generate and hold the object instance. In other words, when the ARC function is valid, the call of the NSAllocateObject function is also forbidden. If used, the following compilation error is also encountered.
Error: 'nullobject' is unavailable:
Not available in automatic reference counting mode. Similarly, the NSDeallocateObject function used when an object is released cannot be used.
NSZone cannot be used
What is NSZone? NSZone is a measure to prevent memory fragments from being imported. Zone is the basic unit of memory management. It manages the plural zones in the system. The system allocates the Zone of an object based on its purpose and size. To improve object access efficiency and avoid unnecessary memory fragments. However, the current runtime system (specified by the compile switch _ OBJC2 _) does not support the concept of Zone. Therefore, NSZone cannot be used no matter whether the ARC is valid or not.
You cannot explicitly call dealloc.
Whether or not ARC is used, when an object is released, the dealloc function of the object is called (just like the destructor of the object in C ++ ). In this function, you need to release some memory. For example, if the object uses the C language memory space allocated by malloc, dealloc needs to process the memory release as follows.
1
2
3
4-(void) dealloc
{
Free (buffer _);
}
Or a registered delegate object. When the observer object needs to be deleted, it also acts in the dealloc function.
1
2
3
4-(void) dealloc
{
[[Nsicationcenter center defacenter center] removeObserver: self];
}
If the ARC is invalid, call the dealloc function of the parent class object as follows.
1
2
3
4-(void) dealloc
{
[Super dealloc];
}
However, when the ARC is valid, the call of [super dealloc]; has been automatically executed by the compiler and does not need to be explicitly called. If you write the code like this, you will inevitably encounter the following errors.
Error: ARC forbids explicit message send of 'dealloc'
[Super dealloc];
^ ~~~~~~~ Memory management-related functions must follow naming rules
In-depth introduction to iPhone Development (3)-functions starting with alloc/new/copy/mutableCopy/init in the past and present of ARC, the ownership of the object must be returned to the caller. This rule should be followed no matter whether the ARC is valid or not. Functions starting with init are special. They only have requirements under ARC and are extremely harsh.
Functions starting with init can only return the id type, or the object type of the class/parent class to which the function belongs. Basically, the init function initializes the returned values of the alloc function, and then returns the object. For example:
Id obj = [[NSObject alloc] init]; for example, the function defined below is incorrect:
-(Void) initThisObject; it must be as follows:
-(Id) initWithObject :( id) obj; In addition, the following function named initialize is special. The Compiler filters it out and does not process it according to the above rules.
Use @ autoreleasepool instead of NSAID utoreleasepool
Under ARC, we can no longer use the native utoreleasepool in code. When we write the main. m file, we usually write it like below.
1
2
3
4
5
6 int main (int argc, char * argv []) {
NSAID utoreleasepool * pool = [[NSAID utoreleasepool alloc] init];
Int retVal = UIApplicationMain (argc, argv, nil, nil );
[Pool release];
Return retVal;
}
When the ARC is valid, @ autoreleasepool should be used to replace the NSAID utoreleasepool.
1
2
3
4
5
6 int main (int argc, char * argv [])
{
@ Autoreleasepool {
Return UIApplicationMain (argc, argv, nil, NSStringFromClass ([AppDelegate class]);
}
}
When the compiler sees the block defined by @ autoreleasepool, it will automatically generate the NSAID utoreleasepool object and put the required object into the AutoReleasePool. When the block definition range is exceeded, the object in the pool will be released.
The Objective-C object cannot be a member of the C language struct (struct/union ).
When we set the ARC to be valid and define the Objective-C object in the structure of the C language, a compilation error similar to the following will occur.
1
2
3 struct Data {
NSMutableArray * array;
};
Error: ARC forbids Objective-C objs in structs or unions
NSMutableArray * array;
^ Because ARC delegates the details of memory management to the compiler, the compiler must manage the object lifecycle. LLVM 3.0 does not have a memory management method for members of the C language constructor. If the object is a stack object, the life cycle of the object can be easily maintained by using the inbound and outbound stack principles. The struct structure is not feasible. In a simple understanding, the struct has no destructor, the compiler itself cannot automatically release its internal Objective-C object.
When we must add an Objective-C object to the structure of C language, we can use void * transformation or the keyword _ unsafe_unretained. For example:
1
2
3 struct Data {
NSMutableArray _ unsafe_unretained * array;
};
In this way, the memory information is not in the compiler memory management object. It is only used and has no permission to hold the object. Of course, the owner of an object must clearly manage the interaction between the object and the struct, so do not cause unnecessary errors 3.
Cast must be specified between [id] and [void *].
When ARC is effective, we don't need to worry too much because the compiler helps us manage the memory. However, when interacting with object types other than ARC management, special transformation keywords are required to determine the ownership.