程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> objective C 內存管理及屬性方法詳解

objective C 內存管理及屬性方法詳解

編輯:關於C語言

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;

-(NSString*)title
{
return title;
}
-(void)settitle:(NSString*)newtitile

{

//首先判斷是否與舊對象一致,如果不一致進行賦值。

if(newTitle!=title)

{

[title release];
title=[newtitile copy];

}

}



retain:會自動retain對象,實現

代碼如下:

@property (nonatomic,retain) NSString *title;

-(NSString*)title
{
return title;
}
-(void)settitle:(NSString*)newtitile

{

//首先判斷是否與舊對象一致,如果不一致進行賦值。

//對於nil對象執行release,不會拋異常,如果不會nil,release正好釋放舊的對象,這樣就可以保證不會出現內存洩露

//因為如果是一個對象的話,進行if內的代碼會造成一個極端的情況:當此name的retain為1時,使此次的set操作讓實例name提前釋放,而達不到賦值目的。

if(newTitle!=title)

{

[title release];
title=[newtitile retain];

}

}

在對屬性進行賦值時,會調用屬性的set方法,使引用計數加一從而保證內存的正確引用。

自定義的類是不能用COPY的,因為自定義的類沒有實現協議,該協議裡面有各種copy方法,所以,copy別亂用,盡量只在設置字符串時使用。

assign,retain 和 copy的區別

  • copy: 建立一個索引計數為1的對象,然後釋放舊對象
  • retain:釋放舊的對象,將舊對象的值賦予輸入對象,再提高輸入對象的索引計數為1
  • assign:直接復制,並未創建新的對象

    比如一個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地址為0×3333,內容為3333,在棧上分配空間,地址為0X3333,內容為“hello”,新的對象retainCount為1,str對象沒有變化,對newStr執行刪除操作只會涉及其本身,與str無關 retain:NSString *newStr=[str retain];

    newStr地址為0X4444,內容為1111,str的retaincount++,

    assign就是直接賦值,刪除時可能引起問題,當數據為int, float等原生類型時,可以使用assign。retain使用了引用計數,retain引起引用計數加1, release引起引用計數減1,當引用計數為0時,dealloc函數被調用,內存被回收。copy是在你不希望a和b共享一塊內存時會使用到。a和b各自有自己的內存。



  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved