你好,歡迎來到IOS教程網

 Ios教程網 >> IOS使用技巧 >> IOS技巧綜合 >> oc內存管理機制

oc內存管理機制

編輯:IOS技巧綜合
[摘要]本文是對oc內存管理機制的講解,對學習IOS蘋果軟件開發有所幫助,與大家分享。

Use Accessor Methods to Make Memory Management Easier

If your class has a property that is an object, you must make sure that any object that is set as the value is not deallocated while you’re using it. You must therefore claim ownership of the object when it is set. You must also make sure you then relinquish ownership of any currently-held value.

Sometimes it might seem tedious or pedantic, but if you use accessor methods consistently, the chances of having problems with memory management decrease considerably. If you are using retain and release on instance variables throughout your code, you are almost certainly doing the wrong thing.

Consider a Counter object whose count you want to set.

@interface Counter : NSObject
@property (nonatomic, retain) NSNumber *count;
@end;
The property declares two accessor methods. Typically, you should ask the compiler to synthesize the methods; however, it’s instructive to see how they might be implemented.

In the “get” accessor, you just return the synthesized instance variable, so there is no need for retain or release:

- (NSNumber *)count {
return _count;
}
In the “set” method, if everyone else is playing by the same rules you have to assume the new count may be disposed of at any time so you have to take ownership of the object—by sending it a retain message—to ensure it won’t be. You must also relinquish ownership of the old count object here by sending it a release message. (Sending a message to nil is allowed in Objective-C, so the implementation will still work if _count hasn’t yet been set.) You must send this after [newCount retain] in case the two are the same object—you don’t want to inadvertently cause it to be deallocated.

- (void)setCount:(NSNumber *)newCount {
[newCount retain];
[_count release];
// Make the new assignment.
_count = newCount;
}

/************************************************/

簡單說就是@{get,set}方法,get方法就不說了,說說set方法

- (void)setCount:(NSNumber *)newCount {
[newCount retain]; //newCount 引用計數+1
[_count release]; //把_count 指針所指向的對象引用計數-1 ,沒有加這句會造成內存洩露
// Make the new assignment.
_count = newCount; //單純的指針賦值
}

/***************************************/

The second uses a convenience constructor to create a new NSNumber object. There is therefore no need for retain or release messages

- (void)reset {
NSNumber *zero = [NSNumber numberWithInteger:0];
[self setCount:zero];
}
Note that both use the set accessor method.

The following will almost certainly work correctly for simple cases, but as tempting as it may be to eschew accessor methods, doing so will almost certainly lead to a mistake at some stage (for example, when you forget to retain or release, or if the memory management semantics for the instance variable change).

- (void)reset {
NSNumber *zero = [[NSNumber alloc] initWithInteger:0];
[_count release];
_count = zero;
}
Note also that if you are using key-value observing, then changing the variable in this way is not KVO compliant.

/**********************************************************/

這是官方寫的一個reset 方法,簡單的說 alloc 出來的對象引用計數+1,所以在不需要的時候需要 release,

[NSNumber numberWithInteger:0]; 這種方法引用計數沒有+1 ,因此再不需要的時候 ,也不需要release,

至於內部是如何實現,本文就不做研究了。

/************************************************************/

Don’t Use Accessor Methods in Initializer Methods and dealloc
The only places you shouldn’t use accessor methods to set an instance variable are in initializer methods and dealloc. To initialize a counter object with a number object representing zero, you might implement an init method as follows:

- init {
self = [super init];
if (self) {
_count = [[NSNumber alloc] initWithInteger:0];
}
return self;
}

/************************************************************/

這個比較重要 ,類的初始化方法 中,不能實現類似 self.count 這樣的方法,這是因為 類似self.count =1;

個人理解是這樣的 init() 方法只有在返回的時候該類才能說被完整的創建。

self.count 相當於 self.getcount();方法 由於 這個方法很有可能被重載了,而導致結果難以預料。 //*注 :如有錯誤歡迎指正

不管如何這個都應該成為我們的設計准則。

/************************************************************/

Use Weak References to Avoid Retain Cycles

Retaining an object creates a strong reference to that object. An object cannot be deallocated until all of its strong references are released. A problem, known as a retain cycle, can therefore arise if two objects may have cyclical references—that is, they have a strong reference to each other (either directly, or through a chain of other objects each with a strong reference to the next leading back to the first).

The object relationships shown in Figure 1 illustrate a potential retain cycle. The Document object has a Page object for each page in the document. Each Page object has a property that keeps track of which document it is in. If the Document object has a strong reference to the Page object and the Page object has a strong reference to the Document object, neither object can ever be deallocated. The Document’s reference count cannot become zero until the Page object is released, and the Page object won’t be released until the Document object is deallocated.

The solution to the problem of retain cycles is to use weak references. A weak reference is a non-owning relationship where the source object does not retain the object to which it has a reference.

To keep the object graph intact, however, there must be strong references somewhere (if there were only weak references, then the pages and paragraphs might not have any owners and so would be deallocated). Cocoa establishes a convention, therefore, that a “parent” object should maintain strong references to its “children,” and that the children should have weak references to their parents.

So, in Figure 1 the document object has a strong reference to (retains) its page objects, but the page object has a weak reference to (does not retain) the document object.

Examples of weak references in Cocoa include, but are not restricted to, table data sources, outline view items, notification observers, and miscellaneous targets and delegates.

You need to be careful about sending messages to objects for which you hold only a weak reference. If you send a message to an object after it has been deallocated, your application will crash. You must have well-defined conditions for when the object is valid. In most cases, the weak-referenced object is aware of the other object’s weak reference to it, as is the case for circular references, and is responsible for notifying the other object when it deallocates. For example, when you register an object with a notification center, the notification center stores a weak reference to the object and sends messages to it when the appropriate notifications are posted. When the object is deallocated, you need to unregister it with the notification center to prevent the notification center from sending any further messages to the object, which no longer exists. Likewise, when a delegate object is deallocated, you need to remove the delegate link by sending a setDelegate: message with a nil argument to the other object. These messages are normally sent from the object’s dealloc method.

/************************************************************/

簡單的解釋下 ,想必大家都對retain,assign,weak,strong這些有所理解,但是什麼時候使用什麼引用呢?

首先官方文檔說明了一種情況 ,就是在 A 引用 B ,B引用C的情況下,這樣就形成了一個閉環,造成內存無法被釋放掉,這個時候怎麼辦?

官方的解決方法是采用 weak和strong 來解決它,只有根部的屬性采用strong 描述,weak 用於描述子的屬性,這樣就能解決循環引用問題。 簡單的說 strong 屬性會令引用計數+1,而weak則不會,這樣就不會造成循環引用。

/**************************************************************/

Ownership Policy Is Implemented Using Retain Counts

The ownership policy is implemented through reference counting—typically called “retain count” after the retain method. Each object has a retain count.

When you create an object, it has a retain count of 1.
When you send an object a retain message, its retain count is incremented by 1.
When you send an object a release message, its retain count is decremented by 1.
When you send an object a autorelease message, its retain count is decremented by 1 at the end of the current autorelease pool block.

If an object’s retain count is reduced to zero, it is deallocated.

Important: There should be no reason to explicitly ask an object what its retain count is (see retainCount). The result is often misleading, as you may be unaware of what framework objects have retained an object in which you are interested. In debugging memory management issues, you should be concerned only with ensuring that your code adheres to the ownership rules.

/**************************************************************/

這是引用計數設計的幾條原則,蘋果特意說明了只需要遵守這幾個准則就行了,任何試圖打印當前引用計數的方法,所得到的結果都可能是錯誤的。

其他的還有一些細節,就不再這裡一一贅述了。

總結一下 :引用計數分為3類:

1.assign

2.copy

3. retain (其中包含 weak和strong 用於解決循環引用問題)

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved