oc為每個對象提供一個內部計數器,這個計數器跟蹤對象的引用計數,當對象被創建或拷貝時,引用計數為1,每次保持對象時,調用retain接口,引用計數加1,如果不需要這個對象時調用release,引用計數減1,當對像的引用計數為0時,系統就會釋放掉這塊內存,釋放對象調用dealloc
當對象包含其他對象時,就得在dealloc中自己釋放他們
NSObject是IOS所有類的基類有兩個基本函數,alloc和dealloc
alloc類似於C++的new,dealloc類似於delete
當對象的retaincount為0時,自動調用dealloc函數
release只是使retaincount-1,不是調用dealloc函數
內存管理的原則:
如果使用alloc,copy創建的對象,一定要release
如果你retain一個對象,那麼必須要release
Song 類的實現
#import
@interface Song : NSObject
{
NSString *_title;
NSString *_artist;
long int _duration;
}
@property (nonatomic,retain) NSString *title;
@property (nonatomic,retain) NSString *artist;
@property (nonatomic,assign) long int duration;
-(Song*)initwithTitle:(NSString *)t AndArtist:(NSString *)art AndDuration:(long int)d;
@end
#import "Song.h"
@implementation Song
@synthesize title=_title;
@synthesize artist=_artist;
@synthesize duration=_duration;
-(Song*)initwithTitle:(NSString *)t AndArtist:(NSString *)art AndDuration:(long)d
{
self=[super init];
if(self)
{
self.title=t;
self.artist=art;
self.duration=d;
}
return self;
}
@end
main函數code
int main(int argc, const char * argv[])
{
Song *Song1=[[Song alloc] initwithTitle:@"what" AndArtist:@"hello" AndDuration:3];
Song *Song2=[[Song alloc] initwithTitle:@"aaa" AndArtist:@"bbb" AndDuration:4];
NSLog(@"Song1 retain count is %ld",[Song1 retainCount]);
NSLog(@"Song2 retain count is %ld",[Song2 retainCount]);
[Song1 retain];
[Song2 retain];
NSLog(@"Song1 retain count is %ld",[Song1 retainCount]);
NSLog(@"Song2 retain count is %ld",[Song2 retainCount]);
[Song1 release];
[Song2 release];
NSLog(@"Song1 retain count is %ld",[Song1 retainCount]);
NSLog(@"Song2 retain count is %ld",[Song2 retainCount]);
[Song1 release];
[Song2 release];
return 0;
}
the result:
2013-05-07 14:44:55.170 Access[2891:303] Song1 retain count is 1
2013-05-07 14:44:55.173 Access[2891:303] Song2 retain count is 1
2013-05-07 14:44:55.173 Access[2891:303] Song1 retain count is 2
2013-05-07 14:44:55.173 Access[2891:303] Song2 retain count is 2
2013-05-07 14:44:55.174 Access[2891:303] Song1 retain count is 1
2013-05-07 14:44:55.174 Access[2891:303] Song2 retain count is 1
內存管理釋放池提供了一個對象容器,每次對象發送autorelease時,對象的引用計數並不真正變化,而是內存釋放池記錄一條記錄,記下該對象的要求,直到內存釋放池發送retain或release時,當池在銷毀之前通知池內所有元素,發送release消息減1,這部分代碼必須放在:
NSAutoreleasePool *pool=[[NSAutoreleasePool alloc]init];
和 [pool release]; 之間
int main(int argc, const char * argv[])
{
NSAutoreleasePool *pool=[[NSAutoreleasePool alloc]init];
NSArray *weeks1=[NSArray arrayWithObjects:@"monday",@"tuesday",@"thursday", nil];
NSArray *weeks2=[[NSArray alloc ]initWithObjects:@"monday",@"tuesday",@"thursday", nil];
//[weeks1 autorelease];
[weeks1 release];
[weeks2 release];
//[weeks2 autorelease];
NSLog(@"retain count is %ld",[weeks1 retainCount]);
NSLog(@"retain count is %ld",[weeks2 retainCount]);
[pool release];
return 0;
}
屬性簡介
@property 和@synthesize 可以自動生成某個類成員變量的存取方法,
語法 @property(參數) 類型 名字
這裡的參數分為三大類:
讀寫屬性:(readwrite/readonly) readwrite:這個屬性是默認的,readonly:只生成getter 不會有setter
原子性(nonatomic)atomic ;是為了保證程序能夠並發,避免同步問題
內存管理:(assign/retain/copy)assign:這個屬性用來處理基礎類型,比如int,float,如果你聲明的類型就是基礎類型,該屬性可以不加
對於assign而言,set函數和get函數如下所示:
@property(nonatomic,assign)int val;
-(int)val
{
return val;
}
(void)setVal:(int)newVal
{
val=newVal;
}
copy:自動生成該對象的克隆
代碼如下:
@property (nonatomic,copy) NSString *title;
{
//首先判斷是否與舊對象一致,如果不一致進行賦值。
if(newTitle!=title)
{
[title release];}
}
retain:會自動retain對象,實現
代碼如下:
@property (nonatomic,retain) NSString *title;
{
//首先判斷是否與舊對象一致,如果不一致進行賦值。
//對於nil對象執行release,不會拋異常,如果不會nil,release正好釋放舊的對象,這樣就可以保證不會出現內存洩露
//因為如果是一個對象的話,進行if內的代碼會造成一個極端的情況:當此name的retain為1時,使此次的set操作讓實例name提前釋放,而達不到賦值目的。
if(newTitle!=title)
{
[title release];}
}
在對屬性進行賦值時,會調用屬性的set方法,使引用計數加一從而保證內存的正確引用。
自定義的類是不能用COPY的,因為自定義的類沒有實現
assign,retain 和 copy的區別
比如一個NSString對象,NSString *str=【NSString alloc】initwithString:@"hello";
在內存分配的過程如下:
首先,在堆上創建一塊內存,內容初始化為“hello”,地址為0X1111
其次,在棧上創建一內存,地址為0X2222,內容為1111,
assign : NSString *newStr=[str assign];
則newStr是str的別名,地址為0X2222,內容為1111,retaincount值不變,對newStr執行刪除操作,則str也會被刪除
copy:NSString *newStr=[str copy];
newStr地址為0X4444,內容為1111,str的retaincount++,
assign就是直接賦值,刪除時可能引起問題,當數據為int, float等原生類型時,可以使用assign。retain使用了引用計數,retain引起引用計數加1, release引起引用計數減1,當引用計數為0時,dealloc函數被調用,內存被回收。copy是在你不希望a和b共享一塊內存時會使用到。a和b各自有自己的內存。