Iphone (object-c) memory management (3) Effective Memory Management first half

Source: Internet
Author: User
Tags notification center

Now I am engaged in iphone development. I have never been very familiar with the object-c memory management mechanism. I can see that apple's official documents are well written and I have not found any translation articles. So I translated it by the way when I was learning it. My English is not very good, and the ability to organize words is even better. I hope you can point out the poor reading, I shall correct the translation in the future. For the first translation, you are welcome to shoot bricks. Don't beat me to death !!!

The words LPSTUDY in the article indicate that they are my personal understanding and may be incorrect. Please kindly advise.


Practical Memory Management
Although many basic concepts in the memory management policy section are clear, you can still take some practical steps to easily manage the memory, it also makes your program more reliable and robust, and reduces its resource requirements.


Use Access methods to make memory management easier
If your class has an object attribute, you must ensure that it cannot be released when you use it. You must also declare the ownership when it is assigned a value, and ensure that the ownership is released.

This is often boring, but if you use the same access method, the possibility of memory management problems will be greatly reduced. If you use the retain and release methods for instance variables in the code, you can almost be sure that you are doing an error.


Now you want to set the count attribute of a Counter object. The Code is as follows:

[Cpp]
@ Interface Counter: NSObject {
NSNumber * _ count;
}
@ Property (nonatomic, retain) NSNumber * count;
@ End;
The property declares two access methods. Generally, you should require the compiler to synthesize the method (synthesize), but it will be helpful to you by looking at their implementation code. In the "get" method, you only need to return instance variables, so there is no need to retain or release

[Cpp]
-(NSNumber *) count {
Return _ count;
}

In the "set" method, if other people follow the same rules, the new count variable may be released at a certain time. To retain this object and obtain its ownership, you must call the retain method. At the same time, you must send a release message to it to release the ownership of the old object it owns (object-c allows sending messages to nil ). You must first call [newCount retain] to prevent yourself from assigning values. If it is released first, the retain operation will be meaningless.

[Cpp]
-(Void) setCount :( NSNumber *) newCount {
[NewCount retain];
[_ Count release];
// Make the new assignment.
_ Count = newCount;
}
Use the access method to set the attribute value
For example, you can implement a method to reset the counter object. You have many options. The first method is to use alloc to create an NSNumber instance and release it.

[Cpp]
-(Void) reset {
NSNumber * zero = [[NSNumber alloc] initWithInteger: 0];
[Self setCount: zero];
[Zero release];
}
The second method is to use a more convenient constructor to create an NSNumber object. Therefore, there is no need for retain or release messages.

[Cpp]
-(Void) reset {
NSNumber * zero = [NSNumber numberWithInteger: 0];
[Self setCount: zero];
}
Note that the above two methods both use the "set" Method

The following example can work normally in simple cases. But just as it aims to avoid access methods, this will always lead to errors in some cases (for example, if you forget retain or release, or if the memory management semantics of the instance variable changes)

[Cpp]
-(Void) reset {
NSNumber * zero = [[NSNumber alloc] initWithInteger: 0];
[_ Count release];
_ Count = zero;
}
Notealso that if you are using key-value observing, then changing the variable inthis way is not KVO compliant. (I do not know kvo yet, but what is kvo)
Do not use the access method in the init and dealloc Methods
The only place where you cannot set variables by using the access method is in the inializer method and dealloc method. To set the initial numeric object to 0, you can implement the following in the init method:

[Cpp]
-Init {
Self = [super init];
If (self ){
_ Count = [[NSNumber alloc] initWithInteger: 0];
}
Return self;
}
To use count to initialize a counter object, you can implement the initWithCount method:

[Cpp]
-InitWithCount :( NSNumber *) startingCount {
Self = [super init];
If (self ){
_ Count = [startingCount copy];
}
Return self;
}
LPSTUDY: This is the initialization method, so you do not need to release it first. I don't quite understand why it calls the copy method, rather than the retain method. Copy is equivalent to applying for another memory with the same data, while retain is equivalent to obtaining the ownership of the original data. If you know, leave a message. Thank you.

Use Weak references to avoid retain Loops
Retain an object creates a strong reference to this object. The memory occupied by this object will not be released until all strong references of an object are release. So there is a problem called "retaincycle.

LPSTUDY:

This is easy to understand, especially as the deadlock in the operating system, a references B, B references c, c references a, and then forms a ring. Or let's just make it simple: a has B and B has. Now I want to release a, so I have to release B first, and I want to release B, I have to release a first, so that the deadlock will lead, no one can release, I don't know if this is easy to understand. If you want to figure out the reference loop carefully, you need to carefully search the relevant technical documents.

A potential reference loop is displayed in icon 1. The Document class has a Page Object for each of its pages. Each Page class also has an attribute to indicate its Document. If the Document object has a strong reference pointing to the Page and the Page class also has a strong reference pointing to the Document class, then no object can be released. The reference count of Document can only be 0 after all Page objects are released. For the Page class, similarly, all Document objects must be released before they can be released, so they are deadlocked.

Figure 1: Example of cyclic reference

 

The solution of retain cycle is to use weak references. Weak references refer to a non-having relationship, that is, the reference of an object does not have the retain object.

Strong references are necessary to maintain the relationship between object graphs. Therefore, Cocoa adopts a convention that "parent" objects should have strong references to their "children", and "children" should have weak references to their "parents.

Therefore, for icon 1, the Document class has a strong reference to its Page, and the Page has a weak reference to the Document class.

Examples of weak references in Cocoa exist, but are not limited to data sources like tables, outline view entries, notification class observers, and a variety of targets and delegates.

When you want to send messages to a weak referenced object, you must be very careful. If this object has been released, the program will crash. Therefore, you must clearly know when this object is valid. In most cases, objects with weak references can perceive all objects with weak references. when an object is released, it must send notifications to the objects that reference it. For example, if you register an object with the notification center, the notification center stores weak references to the object and sends a message to the object when appropriate notifications are sent. If this object is released, cancel the registration with the notification center to prevent messages from being sent to this object. Similarly, if a delegate object is released, you need to delete all the delegate links by sending setDelegate: nil to other objects. This method is usually done in the dealloc method of the delegate object.

LPSTUDY:

My personal understanding (I have not done the entrusting class myself. I just learned the oc, and I feel that this process is best suited to the actual logic, so I wrote it like this. If something is wrong, I hope you can point it out when you look at it. I will correct it again and hope it will not be because of my mistake.) a wants to entrust B to work, in a, you can call the setDelegate: B method to set the delegate of B as a. In this way, a can delegate B, and a will throw all the jobs it wants to do to B, completed by B. If a wants B to work, B must first live, because a does not know when B will die, so B must tell a that he is dead before it dies, don't trust me any more. B tells itself that the messages that fail are implemented by B calling the setDelegate: nil METHOD OF a in its own dealloc.

Do not release the objects you are using
The cocoa object ownership policy ensures that the objects you receive during the entire life cycle of the called method are valid. Similarly, you can return the received object (not very fluent, but you do not know how to translate the received ed objects ). This is not important for whether you return instance variables or calculation results. It is important that when you use it, the object must be valid.

There are some exceptions. Below are two of them.

1. When an object is deleted from the collection class classes
[Cpp]
HeisenObject = [array objectAtIndex: n];
[Array removeObjectAtIndex: n];
// HeisenObject cocould now be invalid.
When an object is removed from the basic collection class, it sends a release method instead of the autorelease method. If this collection class is the only owner of this object, the removed object (like the heisenObject in this example) will be immediately released.
2. When the parent object is released
[Cpp]
Id parent = <# create a parent object #>;
//...
HeisenObject = [parent child];
[Parent release]; // Or, for example: self. parent = nil;
// HeisenObject cocould now be invalid.
In order to prevent such a situation, you need to repeat this object. When you stop using it, release it. For example, in some cases, you obtain an object from another object, and then release the parent object. If the release parent object triggers the dealloc method of the parent object and the parent object is the unique owner of the child, then the child (such as heisenObject in this example) will be released (the dealloc method of the parent object sends a release message to the subclass)

[Cpp]
HeisenObject = [[array objectAtIndex: n] retain];
[Array removeObjectAtIndex: n];
// Use heisenObject...
[HeisenObject release];


Author: lipeng08

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.