In a previous piece of the article we talked about OC predicate operations: http://blog.csdn.net/jiangwei0910410003/article/details/41923507, from today we'll look at the hardest part of OC: Memory management
Why is it difficult for him to say it? Because memory if we need to manage the programmer, the difficulty is certainly very large, if it is Java, the garbage collector will do the job, we do not need to care, but because of this, the speed of Android will slow down, the reason is very simple, Java's garbage collector has a lot of collection algorithms, this in the process of recycling is a waste of time, efficiency is naturally low, but if the job to the programmer to do it, the efficiency will certainly increase, but for programmers, the task is more onerous, but also special care, Do not cause memory overflow and leaks.
Here we mainly from four aspects to introduce memory management
1. Simple examples to understand the use of reference counting
2, set method to control the reference counting problem
3, the destruction method to control the reference counting problem
4. Initialize method to control reference counting problem
Here's a quick look at the memory management in OC
This example is a bit complicated, and we analyze it slowly.
Dog.h
dog.h// 24_memerymanager//// Created by Jiangwei on 14-10-12.// Copyright (c) 2014 Jiangwei . All rights reserved.//#import <Foundation/Foundation.h> @interface dog:nsobject{ nsstring *_name;} -(void) SetName: (NSString *) name; @end
DOG.M
dog.m// 24_memerymanager//// Created by Jiangwei on 14-10-12.// Copyright (c) 2014 Jiangwei. All rights reserved.//#import "Dog.h" @implementation dog-(void) SetName: (NSString *) name{ _name = name;} @end
The name attribute is defined in the dog class, and a set method is provided to him
Person.h
person.h// 24_memerymanager//// Created by Jiangwei on 14-10-12.// Copyright (c) 2014 Jiangwei. All rights reserved.//#import <Foundation/Foundation.h> @class Dog, @interface person:nsobject{ dog *_dog; NSString * _NAME;} -(ID) Initwithdog: (dog*) dog;-(void) SetName: (NSString *) name;-(void) Setdog: (dog *) dog;-(void) playdog;-(dog *) dog;-( void) Dealloc; @end
person.m
person.m//24_memerymanager////Created by Jiangwei on 14-10-12.//Copyright (c) 2014 Jiangwei. All rights reserved.//#import "Person.h" @implementation person-(ID) Initwithdog: (dog*) dog{//When using initialization, pass in Dog self = [s] Uper Init]; if (self! = nil) {//Because the initialization method will only be called once, so there is no judgment [_dog release]; _dog = [dog retain]; } return self;} -(void) SetName: (NSString *) name{//Here name is also an object, so it is also necessary to overwrite _name = name; /*//The judgment here is because the SetName method may be called multiple times if (_name! = name) {[_name release]; [name copy];//uses copy instead of retain, which is unique to strings, other object types are retain} */}//the first way/*-(void) Setdog: (DOG *) dog{//reference count Requires +1 _dog = [dog retain]; Sometimes you might need to replace the dog object, so here's another way to pay attention to the release of the Dog Reference} *///second method/*-(void) Setdog: (DOG *) dog{//using nil to invoke the method is error-free//But when an object is destroyed, the pointer becomes a wild finger The call method will error [_dog release]; _dog = [dog retain];} *///the Third Way-(void) Setdog: (DOG *) dog{//The judgment here is that the SetName method may be called multiple times if (_dog! = Dog) {[_dog release]; _dog = [dog retain]; }}-(void) playdog{NSLog (@ "Playdog");} -(DOG *) dog{return _dog;} -(void) dealloc{//Object type properties are required here to release the reference//to release the dog [_dog release]; NSLog (@ "Dealloc is executing"); [Super Dealloc];} @end
The person class has a property for the dog and then provides a set method. The code is a little complicated, and we'll explain in detail later
Here's a look at the test code
Main.m
main.m//24_memerymanager////Created by Jiangwei on 14-10-12.//Copyright (c) 2014 Jiangwei. All rights reserved.//#import <Foundation/Foundation.h> #import "Person.h" #import "Dog.h"//memory management//alloc used to create objects, After the creation is complete, the reference count is 1, call only once//retain make reference count +1, can call several times//release make reference count-1, can call multiple times//When the reference count is 0 will call dealloc// The latest version of Xcode will open the ARC mechanism by default, and when this mechanism is turned on, we cannot manually display calls to these methods, the compiler will error//So we can turn off this default state of arc, but this is just to test the use of int main (int argc, const char * argv[]) {/* Person *person = [[Person alloc] init];//reference count is 1 NSLog (@ "reference count:%ld", [person Retaincount]) ; Reference count plus 1 [person retain]; [Person release]; NSLog (@ "reference count:%ld", [person Retaincount]); [Person release]; */Dog *dog = [[Dog alloc] init]; [Dog setname:@ "small Black"]; Dog *DOG1 = [[Dog alloc] init];//reference count is 1 [dog setname:@ "rhubarb"]; Person *P1 = [[Person alloc] init]; [P1 setname:@ "Zhang San"]; [P1 Setdog:dog]; [P1 setdog:dog1];//Dog's reference replaced with rhubarb person *p2 = [[Person alloc] init]; [P2 setname:@ "John Doe"]; [P2 Setdog:dog]; Here the reference count is 1, this is inconsistent with the reference count management we said before, so we need to use the manual retain NSLog (@ "reference count:%ld", [dog Retaincount]); [Dog1 release];//because alloc when the reference count is 1///Here is a problem, Dog1 object has been destroyed, but Setdog object is still used Dog1 object Call method, this will be an error//So the Set method is improved [P1 SETDOG:DOG1]; When people destroy, also need to reference to the dog-1//In the human Dealloc method to achieve person *p3 = [[Person alloc] initwithdog:dog1]; [Dog1 release];//dog1 Reference count: 0 [P3 Playdog]; [P3 release]; return 0;}
Let us explain in detail:
First, if you want to demonstrate this example, you need to modify the settings:
The latest Xcode is automatically selected by the arc (Automatic Reference counting), if we do not close this manually, the code will be an error.
alloc is used to create the object, after creation, the reference count is 1and is called only once
retain makes reference count +1, can be called several times
release makes reference count -1, can be called several times
Dealloc is called when the reference count is 0
Golden rule: Each call to Alloc once, you need to call release once, they are two pairs appear
The latest version of Xcode opens the ARC mechanism by default, and when this mechanism is turned on, we cannot manually display calls to these methods, and the compiler will error
So we can turn off the ARC of this default state, but this is just for testing purposes.
At the same time we will find that the main.m file does not automatically release the pool @autoreleasepool.
1. Simple example
Person *person = [[Person alloc] init];//reference count is 1NSLog (@ "reference count:%ld", [person retaincount]);//reference count plus 1[person retain]; [Person release]; NSLog (@ "reference count:%ld", [person Retaincount]); [Person release];
We created a person class and can then print a reference count value: 1
When we call the Retain method, the reference count will be +1, and when we call the release method, the reference count will-1
Once the system discovers that the reference count is 0, it destroys the object and calls the Dealloc method
2. Set method to control reference count
This is a simple example, no problem, now we complicate the problem
Dog *dog = [[Dog alloc] init]; [Dog setname:@ "small black"];D og *dog1 = [[Dog alloc] init];//reference count is 1[dog setname:@ "rhubarb"]; Person *P1 = [[Person alloc] init]; [P1 setname:@ "Zhang San"]; [P1 Setdog:dog]; [P1 setdog:dog1];//Dog's reference replaced with rhubarb person *p2 = [[Person alloc] init]; [P2 setname:@ "John Doe"]; [P2 setdog:dog];//Here The reference count is 1, this and we have previously said that the reference count management is contradictory, so we need to use the manual retainnslog (@ "reference count:%ld", [dog Retaincount]); [Dog1 release];//because alloc when the reference count is 1//There is a problem here, Dog1 object has been destroyed, but Setdog object is still used Dog1 object Call method, this will be an error//So the set method is improved [P1 setdog:dog1];//when the person destroys, also needs to the dog the reference -1//in the person's Dealloc method realizes
We defined two dogs, then set the two dogs through the Setdog method to the P1 object, while the first dog set to the P2 object, when we print the first dog's reference count, found his reference count is 1, the reason is very simple, this 1 is in the alloc time, But now there is a problem because the first dog is quoted by P1 and P2, according to normal conditions, the first dog's reference count is 3. So this time we need to modify the Setdog method in the person class.
-(void) Setdog: (dog *) dog{ //reference count requires +1 _dog = [dog retain]; Sometimes you may need to replace the dog object, so be aware of the release of the Dog reference}
We need to manually increase the reference count of the dog so that it is normal.
Now there is another problem, the above P1 object set the second dog
[P1 setdog:dog1];//Dog's reference replaced with rhubarb
According to the Setdog method above, we also found a problem, now P1 refers to the dog is the second dog, not the first, then this time according to the normal situation of the first dog reference count-1, because he is no longer referenced by P1. So the Setdog method has to be modified:
-(void) Setdog: (Dog *) dog{ //Use nil to call the method is no error //But when an object is destroyed, the pointer becomes a wild pointer, this time the method will be called Error [_dog release]; _dog = [dog retain];}
This is when we call the release method on _dog before assigning a value, which solves the problem above.
But now there is one more question:
[Dog1 release];//because alloc the reference count is 1 NSLog (@ "Dog1:%ld", [Dog1 Retaincount]);//There is a problem here, the Dog1 object has been destroyed, But the Setdog object still uses the Dog1 object call method, this will error//So the set method is improved [P1 SETDOG:DOG1];
After executing the release code, the reference count for Dog1 is 1, which is to continue calling the Setdog method:
-(void) Setdog: (Dog *) dog{ //Use nil to call the method is no error //But when an object is destroyed, the pointer becomes a wild pointer, this time the method will be called Error [_dog release]; _dog = [dog retain];}
This time _dog is DOG1, continue to call the release method, after execution, the reference continues to be 0, the object is released, but this time the value of the dog parameter is still dog1, then the execution retain method will be error, this reason is very simple, Is that we have called the Setdog method two times, set the Dog1 two times. Call the release method one time in the middle. So to solve this problem, we are revising the Setdog method:
The Third Way-(void) Setdog: (Dog *) dog{ //is judged here because the SetName method may be called multiple times if (_dog! = Dog) { [_dog release]; _dog = [dog retain]; }}
I just need to determine if the previous property value is the same as the value you want to set now. This way is no problem, so we later in writing the Set method, this is the template.
3, Destroy method Dealloc Control reference count
Now if P1 is destroyed, then for DOG1 the reference count should be-1, so you need to modify it in the Dealloc method in the person class:
-(void) dealloc{ //Object type properties are required here to release the reference //To release the dog [_dog release]; NSLog (@ "Dealloc is executing"); [Super Dealloc];}
4. Initialize method to control reference count
Now there is another case, if we use the initialization method to set the Dog property value:
-(ID) Initwithdog: (dog*) dog{ //When using initialization, pass in Dog self = [super init]; if (self! = nil) { //Because the initialization method will only be called once, so there is no judgment [_dog release]; _dog = [dog retain]; } return self;}
Our handling here is the same as the Setdog method, but there is no need to make a judgment here, because the initialization method is only called once. So there is no third case of Setdog.
Summarize
This article mainly introduces the concept and usage of memory management in OC, and then continues to introduce the knowledge of memory management.
Introduction and use of---memory management of OC Learning article