一、內存管理的思考方式
內存管理的思想包括以下四點:
1、自己生成的對象,自己所持有
2、非自己生成的對象,自己也能持有
3、不再需要自己持有的對象時,要釋放
4、非自己持有的對象 不能釋放
自己生成的對象自己持有
?alloc 、new、copy、mutableCopy
這些名稱開頭的方法名意味著自己生成的對象只有自己持有;上文中出現了一系列的自己這個詞,可以將自己理解為“對象的使用環境”,也可以理解為編程人員“自身”。下面寫出了自己生成并持有對象的源代碼。我們在這里使用alloc方法:
//自己生成對象并持有對象
id obj =[ [NSObject alloc] init];
//自己持有對象
使用alloc類方法就能自己生成并持有對象。指向生成并持有對象的指針被賦給變量obj,另外,使用new類方法也可以生成并持有對象。和alloc時完全一致的
//自己生成對象并持有對象
id obj =[NSObject new];
//自己持有對象
copy方法利用基于NSCopying方法約定,由各類實現的copyWithZone:方法生成并持有對象副本。與copy方法類似,mutableCopy方法利用基于NSMutableCopying方法約定,由各類實現的mutableCopyWithZone:方法生成并持有對象的副本。 用這些方法生成的對象,雖然是對象的副本,但是和alloc、new一樣,在”自己生成并持有對象“這點上沒有發生改變;
非自己生成的對象,自己也能持有
用alloc/new/copy/mutableCopy以外的方法取得的對象,因為非自己生成并持有,所以自己不是該對象的持有者。看以下源代碼:
//取得非自己生成并持有的對象
id obj = [NSMutableArray array];
//取得對象的存在,但自己不持有對象
上述代碼中,NSmutableArray類對象被賦值給變量obj,但變量obj自己并不持有該對象。使用retain方法可以持有對象
//取得非自己生成并持有的對象
id obj = [NSMutableArray array];
//取得對象的存在,但自己不持有對象
[obj retain];
//自己持有對象
通過retain方法,非自己生成的對象跟用alloc/new/copy/mutableCopy方法生成并持有的對象一樣,成為了自己所持有的。
不再需要自己持有的對象時 ,要釋放
自己持有的對象,一旦不在需要,持有者有義務釋放該對象。釋放使用release方法。
//自己生成并持有對象
id obj = [[NSObject alloc] init];
//自己持有對象
[obj release];
//釋放對象,指向 對象的指針? 仍然被保留在變量obj中,貌似可以訪問。但是
對象一經釋放不可訪問
如此,用alloc方法由自己生成并持有的對象就通過release方法釋放了。自己生成而非自己所持有的對象,若用retain方法變為自己持有,也同樣可以用release方法釋放。
//取得非自己生成并持有的對象
id obj = [NSMutableArray array];
//取得對象存在,但自己不持有對象
[obj retain];
//自己持有對象
[obj release];
//釋放對象,
對象? 不可再被訪問
那么如果要用某個方法生成對象,并將其返還給該方法的調用方,那么它應該怎么操作呢,如下:
- ( id ) allocObject
{
??????? //自己生成并持有對象
?????? id obj = [[NSObject alloc ] init ];
??????? //自己持有對象
????? return obj;
}
如上,原封不動返回用alloc方法生成并持有的對象,就能讓調用方也持有該對象。
//取得非自己生成并持有的對象
id obj1 = [obj0 allocObject];
//自己持有對象
那么,如何像調用[NSMutableArray array] 方法使取得的對象存在,但自己不持有對象,又是如何實現的呢?如下:
- ( id ) allocObject
{
??????? //自己生成并持有對象
???? ?? id obj = [[NSObject alloc ] init ];
?????? [obj autorelease];
?????? //取得對象的存在,但是自己不持有對象。
??????? return obj;
}
上述代碼中,我使用了autorelease方法。用該方法,可以使取得的對象存在,但自己不持有對象。以后有時間我會詳細介紹autorelease。
id obj1 = [obj0 object];
//取得的對象存在,但自己不持有對象。
當然也可以像前文中的NSMutableArray一樣,通過retain 方法,將調用autorelease方法取得的對象變為自己持有。
無法釋放非自己持有的對象
對于由alloc/new/copy/mutableCopy 方法生成并持有的對象,或是retain方法持有的對象,由于持有者是自己,所以在不需要該對象的時候,需要將其釋放。而由此以外所得到的對象絕對不能釋放。如果在應用程序中釋放了非自己所持有的對象就會造成崩潰。例如自己生成的并持有對象后,在釋放完不再需要的對象之后再次釋放。
//自己生成并持有對象
id obj = [[NSObject alloc] init];
//自己持有對象
[objc release];
//對象已被釋放
[obj release];
//釋放之后再次釋放已非自己持有的對象,應用程序崩潰
//崩潰情況:再度廢棄一經廢棄了的對象時崩潰?? 、 訪問一經廢棄的對象時崩潰;
或者在“取得的對象存在,但自己不持有對象”時釋放
id obj1 = [obj0 object];
[obj1 release];
//釋放了非自己持有的對象,這肯定會導致應用程序崩潰
如這些例子所示,釋放非自己持有的對象會造成程序崩潰。因此絕對不要去釋放非自己持有的對象。