內存管理
MRC——手動管理內存
ARC——自動管理內存
MRC
OC採用“引用計數”(retainCount)方式管理對象佔用的內存
1. 使用alloc爲對象分配內存;使用dealloc釋放對象所佔用的內存。
2. 使用alloc、new或者copy構造對象是,對象的retainCount爲1.
3. 調用對象的retain方法可以增加1 retainCount。
4. 調用對象的release方法可以減少1 retainCount。
5. 當對象的retainCount爲0時,dealloc會自動調用,釋放對象內存;否則分配的內存講被一直佔用。
6. 所有對象可以使用retainCount屬性查看當前的計數器值。
例子:
NSString *dadyCar = [[NSStringalloc]initWithFormat:@”Car”];// dadyCar擁有對象所有權retainCount+1
NSString *mumCar = [dadyCar retain];// mumCar擁有對象所有權,retainCount+1
NSString *sonCar = [mumCar retain];// sonCar擁有對象所有權,retainCount+1
NSString * friendCar = sonCar;// friendCar不擁有對象的所有權,只是簡單指向對象內存空間,retainCount不會發生變化
[dadyCar release];// retainCount-1
[mumCar release];// retainCount-1
[sonCar release];// retainCount-1
注意:
如果所有擁有對象的引用都釋放了對象的所有權(retainCount=0),那麼friendCar就變成了“野指針”,因爲對象已經不存在,不能再調用對象的資源。
@property(retain,nonatomic)Strdent
一個類中,如果這個類有屬性聲明retain或者copy的屬性,那麼我們需要再這個類的dealloc方法裏面釋放這個屬性。
dealloc方法在對象引用計數爲0是自動調用。
主要用於適當自身所佔用的資源。永遠不要手動調用dealloc,應由系統自動調用。
真正釋放對象內存空間的方位爲:dealloc
當一個對象引用計數變成1時,再調用release的時候,其release就會自動調用系統的dealloc方法去釋放對象所佔的空間。
一般在類中需要overwrite覆蓋/重寫/複寫dealloc方法,進行屬性控制。
-(void)dealloc//相當於C++的析構方法
{
//釋放子類的引用
[super dealloc];//調用父類的dealloc,釋放父類
}
內存釋放原則一:
對象分配內存,並應在使用後,調用release釋放內存。
凡是出現retain alloc copy的地方,都應該出現release與之匹配調用。
內存釋放原則二:
內存無法確定釋放時間是,可以使用autorelease向最近池註冊。
有池決定釋放時間
使用便利構造器獲得的對象,都應該是autorelease的。
Autorelease://自動釋放
——延時釋放對象內存。
對於每一個Runloop, 系統會隱式創建一個Autoreleasepool,這樣所有的release pool會構成一個象CallStack一樣的一個棧式結構,在每一個Runloop結束時,當前棧頂的Autorelease pool會被銷燬,這樣這個pool裏的每個Object會被release。
例子:除了大括號之後,會自動release。
(1) 當創建的對象未來某個時候銷燬是,可以使用對象的autorelease。
(2) 對象講所有管理權交給最近的NSautoreleasePool對象,並由其全權釋放。
Autoreleasepool://自動釋放池
對象使用autorelease釋放的會放進Autoreleasepool,系統自動釋放。
例子:
//
// People.h
// Memory
//
// Created by 5016 on 13-12-4.
// Copyright (c) 2013年 dradon. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface People : NSObject
//成員屬性
@property(retain,nonatomic)NSString* name;
@property(assign,nonatomic)NSInteger age;
-(People *)initWithName:(NSString*) name andAge:(NSInteger) age;
+(People *)PeopleWithName:(NSString*) name andAge:(NSInteger) age;
-(void)toString;
@end
//
// People.m
// Memory
//
// Created by 5016 on 13-12-4.
// Copyright (c) 2013年 dradon. All rights reserved.
//
#import "People.h"
@implementation People
@synthesize name=_name,age=_age;
-(People *)initWithName:(NSString*) name andAge:(NSInteger) age
{
if(self = [super init])
{
_name = name;
_age = age;
}
return self;
}
//便利構造器
+(People *)PeopleWithName:(NSString*) name andAge:(NSInteger) age
{
People *person = [[People alloc] initWithName:name andAge:age];
return [person autorelease];//向自動釋放池註冊
}
-(void)toString
{
NSLog(@"我的名字是%@,今年%ld歲.",_name,_age);
}
//重寫(overwirte)父類方法
-(void)dealloc//用來釋放對象的方法,相當於C++裏面的析構方法
{
NSLog(@"這個對象被完全釋放");
self.name = nil;//等價於[_name release]或者[self.name release];
[super dealloc];
}
@end
//
// main.m
// Memory
//
// Created by 5016 on 13-12-4.
// Copyright (c) 2013年 dradon. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "People.h"
int main(int argc, const char * argv[])
{
NSLog(@"|-----------使用alloc開闢對象堆內存空間按-----------------|");
People *person1 = [[People alloc]initWithName:@"DRAGON" andAge:23];//alloc開闢對象 +1
[person1 toString];
NSLog(@"person1的引用計數是:%ld",[person1 retainCount]);
[person1 retain];//+1 = 2
NSLog(@"person1的引用計數是:%ld",[person1 retainCount]);
[person1 release];//-1 = 1 ;這裏對象已經釋放一次,引用計數爲1
NSLog(@"person1的引用計數是:%ld",[person1 retainCount]);
[person1 release];//-1 = 0 ;這裏對象再釋放一次,引用計數爲1-1,系統自動調用dealloc
NSLog(@"person1的引用計數是:%ld",[person1 retainCount]);
//[person1 release];//再調用一次,則是過度釋放,會出現異常
NSLog(@"|-----------使用便利構造器-----------------|");
@autoreleasepool {//使用自動釋放池進行釋放,因爲程序結束後會釋放
People *person = [People PeopleWithName:@"dragon" andAge:20];
[person toString];//使用便利構造器 不需要使用release
}
return 0;
}
運行結果:
相信到了這裏大家會基本理解內存管理.