object-c 內存管理(2) 內存管理策略 – iPhone手機開發技術文章 iPhone軟體開發教學課程

{

    Person *aPerson = [[Person alloc] init];

    // …

    NSString *name = aPerson.fullName;

    // …

    [aPerson release];

}

 

通過使用alloc方法,Person對象被創建,因此當它不再被使用時,它隨後調用release方法。Person的姓名沒有使用任何的獲取擁有權的方法,因此它也沒有調用release方法。註意:本例子使用瞭release而不是autorelease

 

使用autorelease發送延遲釋放消息

當你需要發送延遲釋放消息的時候,你可以使用autorelease,典型的使用時候是當你需要從一個方法中返回一個對象。例如,你可以像這樣實現fullName方法:

– (NSString *)fullName {

    NSString *string = [[[NSString alloc] initWithFormat:@"%@ %@",

                                          self.firstName, self.lastName] autorelease];

    return string;

}

你通過帶調用alloc方法擁有瞭這個字符串。為瞭遵循內存管理規則,在你失去對string的訪問權限之前,你必須釋放string的所有權。如果你采用瞭release方法,那麼string就會在它被返回之前被釋放.通過使用autorelease,你表明你想去釋放擁有權,但是你又允許方法的調用者在它釋放之前去使用返回的字符串。

 

你也可以像下面這樣實現fullName方法:

– (NSString *)fullName {

    NSString *string = [NSString stringWithFormat:@"%@ %@",

                                 self.firstName, self.lastName];

    return string;

}

 

遵循基本的規則,你通過調用stringWithFormat,你並沒有擁有string。因此,你可以安全的從方法中返回string。

 

作為對照,下面的實現是錯誤的

– (NSString *)fullName {

    NSString *string = [[NSString alloc] initWithFormat:@"%@ %@",

                                         self.firstName, self.lastName];

    return string;

}

通過命名的約定,毫無疑問fullName的調用者擁有瞭返回的string,但是調用者沒有任何理由去釋放返回的string,於是string所占用的內存泄露瞭。

 

你並不擁有返回引用的對象的所有權

在cocoa中有一些方法是通過引用返回的(也就是說,它們傳遞瞭一個這樣的參數ClassName ** or id *).一個通常的模式是使用NSError對象來返回錯誤的詳細信息,如 initWithContentsOfURL:options:error: (NSData)andinitWithContentsOfFile:encoding:error: (NSString).

 

在這些情況下,上述描述的規則依然適用。當你觸發它們的任何一個方法的時候,你並沒有創建NSError對象,因此你並沒有擁有它,你也就沒有必要去釋放它。例子如下:

NSString *fileName = <#Get a file name#>;

NSError *error = nil;

NSString *string = [[NSString alloc] initWithContentsOfFile:fileName

                        encoding:NSUTF8StringEncoding error:&error];

if (string == nil) {

    // Deal with error…

}

// …

[string release];

 

 

釋放所有者對象的dealloc的實現                         

NSObject定義瞭一個dealloc方法,當一個對象沒有擁有者而且它的內存被回收的時候,dealloc方法會被自動觸發。Dealloc方法是為瞭釋放對象的內存,安排它所擁有的資源,當然這也包含它擁有的實例變量。

 

下面的例子展示瞭在Person 類中怎麼使用dealloc方法

@interface Person : NSObject {}

@property (retain) NSString *firstName;

@property (retain) NSString *lastName;

@property (assign, readonly) NSString *fullName;

@end

 

@implementation Person

@synthesize firstName=_firstName, lastName=_lastName;

// …

– (void)dealloc

    [_firstName release];

    [_lastName release];

    [super dealloc];

}

@end

 

Attention:

·     你從不要去主動觸發另一個對象的dealloc方法。

·     在自己的dealloc實現的末尾,你必須觸發基類的dealloc方法

·       你不應該把系統資源的管理和對象的生命周期綁定到一起。see “Don’t Usedealloc to Manage Scarce Resources.

·     當程序終止時,對象可能並沒有觸發dealloc方法。由於在程序退出的時候,程序所占有的內存被自動清理,因此,僅僅讓操作系統自己去清理資源比單純的觸發內存管理方法更有效。

 

Core Foundation使用相似但是不同的規則

對於Core Foundation,有相似的內存管理規則(see MemoryManagement Programming Guide for Core Foundation). 但是,Cocoa和Core Foundation的命名規范是不同的,特別的是:CoreFoundation的創建(see “The CreateRule” in MemoryManagement Programming Guide for Core Foundation)

規則並不適用於返回object-c對象的方法。例如,在下面的代碼片段,你不需要釋放myInstance的所有權。

MyClass *myInstance = [MyClass createInstance];

作者:lipeng08

發佈留言