1. 程式人生 > >iOS之屬性定義和記憶體管理

iOS之屬性定義和記憶體管理

當把屬性的語義特性分別宣告為assign,retain,copy時, 自動生成setter, getter方法內部實現

假定有一個車類Car.h中定義三個屬性
@property (nonatomic, retain) NSString * brand; //品牌
@property (nonatomic, copy) NSString * colour;  //顏色
@property (nonatomic, assign) CGFloat  price;   //價格

以下是把屬性的語義特性分別宣告為assign,retain,copy時, 自動生成setter, getter方法內部實現:

//當把屬性的語義特性宣告為retain

,自動生成setter方法內部實現

    - (void)setBrand:(NSString *)brand

    {

       if (_brand != brand) {//如果舊值不等於新值

            [_brand release];//舊值先release

            _brand = [brand retain];//新值retain賦值給舊值

        }

    }

//當把屬性的語義特性宣告為retain,自動生成getter方法內部實現

    - (NSString *)brand

    {

       return [[_brand retain] autorelease];

    }

//當把屬性的語義特性宣告為copy,自動生成setter方法內部實現

    - (void)setColor:(NSString *)color

    {

       if (_color != color) {

            [_color release];

            _color = [color copy];

        }

    }

//當把屬性的語義特性宣告為copy,自動生成getter方法內部實現

    - (NSString *)color

    {

       return [[_color retain] autorelease];

    }

//當把屬性的語義特性宣告為assign,自動生成setter方法內部實現

    - (void)setPrice:(CGFloat)price

    {

        _price = price;

    }

//當把屬性的語義特性宣告為assign,自動生成getter方法內部實現

    - (CGFloat)price

    {

       return _price;

    }

對於Retain和Assign屬性的理解

比如我要定義一下字串var:

NSString *var;

宣告Property時,

@property(nonamtic,assign)NSString *var;

將屬性宣告為Assign,當使用@Synthsize生成Getter和Setter方法後,我們就可以用“.”操作符來為var賦值,

將屬性宣告為Assign時,Setter方法的實現是這樣的:

-(void)setter: (NSString*)str
{
   var=str;
}
var=[[NSString alloc]initWithString: @"aaa"];

當我們這樣用時,沒有呼叫Setter方法,只是將var指向目標地址,這時

NSLog(@“%d”,[var retainCount]);的值會是1。

如果我們這樣寫:self.var=[[NSString alloc] initWithString:"aaa"];

這時會呼叫setter方法,但是NSLog(@“%d”,[var retainCount]);的值仍然是1。

如果我們在設定屬性時這樣來設定:

@property(nonamtic,retain)NSString *var;

這時,自動生成的Setter方法是這樣的:

-(void)Setter:(NSString*)str
{
  [str retain];
  [var release];
  var=str;
}

這樣就一目瞭然了,也就是被設定為retain屬性的方法,在生成Setter方法時,先將要賦的值的引用計數加1,然後將var指向的物件release。再後才是將str賦值給var。這時下面的程式碼的輸出結果會是2,因為,

在Setter中[[NSString alloc]initWithString:"aaa"]所指的記憶體區域的retain被加了1,然後var又指向這個區域,所以var的retainCount自然就為2了:

self.var=[[NSString alloc]initWithString: @"aaa"];
NSLog(@“%d”,[var retainCount]);

這樣做是為了防止記憶體被過渡釋放,比如,

[[NSString alloc]initWithString:"aaa"]這個記憶體區域不光有var指向,還有另外一個變數var2也指向這個區域,如果我們不設定成retain屬性,在執行var=[[NSString alloc]initWithString:"aaa"];後,var和var1都指向一個共同的記憶體區域,但這個記憶體區域的retainCount為1。

如果在另一個地方執行了[var2 release];這樣[[NSString alloc]initWithString:"aaa"]所指的記憶體區域的retainCount為0,所以這個記憶體區域就被釋放了,var也就成了野指標,這時再引用var將會出現記憶體錯誤。

但是,需要特別注意的是,即使我們設定var的屬性為retain,如果我們在為var賦值時,使用的是如下形式:

var=[[NSString alloc]initWithString: @"aaa"];

而不是:

self.var=[[NSString alloc]initWithString: @"aaa"];

這樣retain屬性是不起作用的,前面不加self.,相當於我們定義的屬性還是assign。retainCount不會加1的。

我個人對這個的理解是,如果不顯示的使用"."操作符,Setter方法是不呼叫的,僅僅是指標的傳遞。

今天又有了點新的想法,補充一下:

"."操作符在OBJC中是方法的呼叫,比如:self.str和[self str]是一樣的。如果我在.h檔案中聲明瞭一個方法:

-(void)method;

那麼,我呼叫這個方法可以用兩種方式:[self method]或self.method。

這樣說的話,我們為什麼可以用諸如self.str這樣的形式來表示一個變數呢,原因就在於OBJC中變數屬性的機制。

我們前面說過,定義一個變數str,加個assign或retain之類的屬性後,再用@synthesize就可以生成相應的setter和getter方法了。這樣,對於一個變數,就有了相應的賦值方法,於是,對於self.str這樣的寫法,實際上就是呼叫了str對應的setter或getter方法。換句話說,也是把setter或getter訊息傳送給和str。str這時就是一個方法名,而不僅僅是變數名了。

所以如果我們沒有對一個變數宣告屬性,也沒有@synthesize來生成setter和getter方法,那麼我們就不能用self.str這種形式,而只能用[email protected]"aaa",或者str1=str這樣的形式來使用變數。於是也就有了我們前面的結論:用self.str這種形式,相當於呼叫setter或getter方法。也就會執行retain的操作。不用這種形式,就沒用呼叫setter或getter方法,retain的操作也就無從談起。

如果你用self._myObject = aMyObject; 或者 myObject = aMyObject; 你會得到一個錯誤, 為什麼呢, 這裡就是和Obj-c的存取方法有關了. 說白了很簡單 , 大家都知道, @property (nonatomic, retain) MyObject *myObject; 是為一個屬性設定存取方法, 只是平時我們用的方法名和屬性名是一樣的,現在你把它寫成不同的名字, 就會很清楚了. _myObject是屬性本身, myObject是存取方法名.

順便說一下, 如果你想在其它類訪問物件屬性, 而不是通過存取方法, 你可以用myClass -> myObject來訪問, 這樣是直接訪問物件本身, 不過你先要把myObject設成@public. 但這個是官方不提倡的


相關推薦

iOS屬性定義記憶體管理

當把屬性的語義特性分別宣告為assign,retain,copy時, 自動生成setter, getter方法內部實現 假定有一個車類Car.h中定義三個屬性 @property (nonatomic

Objective-C高階程式設計:iOS與OS X多執行緒記憶體管理

這篇文章主要給大家講解一下GCD的平時不太常用的API,以及文末會貼出GCD定時器的一個小例子。 需要學習的朋友可以通過網盤免費下載pdf版 (先點選普通下載-----再選擇普通使用者就能免費下載了)http://putpan.com/fs/cy1i1beebn7s0h4u9/ 1.G

[讀書筆記]iOS與OS X多執行緒記憶體管理 [GCD部分]

3.2 GCD的API 蘋果對GCD的說明:開發者要做的只是定義想執行的任務並追加到適當的Dispatch Queue中。 “Dispatch Queue”是執行處理的等待佇列。通過dispatch_async函式等API,在Block

.NET基礎型別語法基礎記憶體管理基礎

轉自:http://www.cnblogs.com/edisonchou/p/4787775.html   型別語法基礎和記憶體管理基礎  Index : (1)型別語法、記憶體管理和垃圾回收基礎 (2)面向物件的實現和異常的處理 (3)字串

讀《Objective-C高階程式設計iOS與OS X多執行緒記憶體管理

最近一週,公司在廣州有釋出會。去廣州的人很忙,留在公司的開發人員有時也很“忙”。趁著空閒的時間,看了《Objective-C高階程式設計iOS與OS X多執行緒和記憶體管理》這書,網上找的pdf版本。 這本書分三給部分,依次是ARC、Blocks和GCD。 ARC從非

讀書筆記:Objective-C高階程式設計 iOS與OS X多執行緒記憶體管理 ——(持續)

1.記憶體管理的思考方式: .自己生成的物件,自己所持有.非自己生成的物件,自己也能持有不再需要自己持有的物件時釋放非自己持有的物件無法釋放由NSObject類擔任下面管理職責 eg:  /

python學習二:python資料結構記憶體管理

python資料結構和記憶體管理思維導圖:對於資料結構的學習主要從這幾方面入手:初始化常用操作(增刪該查)常用內建函式,注意點有序序列主要分為字串,列表,和元組,一.有序序列定義:str1=‘python’//字串l1=['python','java','c',100]  o

《Objective-C 高階程式設計 iOS與OS X多執行緒記憶體管理》 核心札記一

蘋果原始碼不會告訴你的 ——引子 近日偶借一本圖靈出版的程式書籍,是由日本資深軟體工程師 K.S. (Twitter:@splhack) 和 TF (Twitter:@munakoiso) 合作編寫,國內 黎華 譯,全書共三章,分別是 ARC,Blocks 和 Grand

《Objective-C 高階程式設計 iOS與OS X多執行緒記憶體管理》 核心札記二

核心札記二   Blocks   閱讀地點:北京 肯德基店  2014.4.7 1,Blocks 是C 語言的擴充功能,用一句話概述就是:帶有自動變數(區域性變數,作者將此翻譯成自動變數)的匿名函式

計算機原理學習(6)-- x86-32 CPU記憶體管理分頁管理

前言 上一篇我們瞭解了x86-16 CPU計算機的記憶體訪問方式,定址方式,以及基於MS-DOS的應用程式的記憶體佈局。這一篇會主要介紹32位處理器的記憶體訪問,記憶體管理以及應用程式的記憶體佈局。雖然目前64位CPU已經非常普及了,不過相對於32位的記憶體管理方式並沒

【Objective-C高階程式設計】iOS與OS X多執行緒記憶體管理

1. __weak修飾符的優點,除了解決迴圈引用的問題,在持有某物件的弱引用時,若該物件被廢棄,則此弱引用將自動失效並且處於nil被賦值的狀態(空弱引用)。 如: id __wark obj1 = nil; { id _strong obj0 = [[NSObject

pythonClass屬性定義訪問

1、python中類定義: 類的宣告和函式的宣告形式是差不多的,開始都是關鍵字+自定義名稱 定義例項變數:可以在定義方法的時候直接定義,也可以使用例項來定義 可以使用dir(ClassName) ClassName.__dict__來檢視有哪些類屬性

Objective-C高階程式設計:iOS與OS X多執行緒記憶體管理讀書筆記

Objective-C高階程式設計:iOS與OS X多執行緒和記憶體管理 自動引用計數 自動引用計數(ARC,Automatic Reference Counting) “在LLVM編輯器中設定ARC為有效狀態,就無需再次鍵入retain或者是releas

Objective-C高階程式設計 iOS與OS X多執行緒記憶體管理 讀書筆記(一)

1.2.2 記憶體管理原則: 自己生成的物件,自己所持有 非自己生成的物件,自己也能持有 不再需要自己持有的物件時釋放 非自己持有的物件無法釋放 自己生成的物件,自己所持有 //自己生成並持有物件 id obj = [[NSObject alloc] init]; //自己持有物件   

(筆記)Linux內核學習(八)定時器時間管理

全局變量 define 結構 load 統計 object 一個 完成 溢出 一 內核中的時間觀念 內核在硬件的幫助下計算和管理時間。硬件為內核提供一個系統定時器用以計算流逝的時間。系 統定時器以某種頻率自行觸發,產生時鐘中斷,進入內核時鐘中斷處理程序中進行

使用OCLintSonar對iOS代碼分析質量管理

環境 測試 版本 ann true onf brew Coding 模板 OCLint 是一個強大的靜態代碼分析工具,可以用來提高代碼質量,查找潛在的bug,主要針對c,c++和Objective-c的靜態分析。 Sonar 是一個用於代碼質量管理的開放平臺。通過插件機制,

Linux學習筆記1——檔案目錄管理(硬連線軟連線)(連結檔,相當於快捷方式)

在這節將要學習linux的連線檔,在之前用"ls -l" 檢視檔案屬性的命令時, 其中第二個屬性是連線數。那麼這個連線數是幹什麼的?這就要理解inode。     先說一下檔案是怎麼儲存的。檔案儲存在硬碟上,硬碟的最小儲存單位叫做"扇區"(Sector),每個扇區儲存512位元

C儲存類、連結記憶體管理--動態分配記憶體及型別限定詞

文章目錄 儲存類說明符 儲存類和函式 動態分配記憶體 `malloc`函式 `free`函式 `calloc`函式 動態分配記憶體的缺點 C型別限定關鍵字

全面理解Unity載入記憶體管理

轉載至蠻牛論壇,原文地址:http://www.unitymanual.com/thread-31097-1-1.html unity

啟動期間的記憶體管理bootmem_init初始化記憶體管理–Linux記憶體管理(十二)

1. 啟動過程中的記憶體初始化 首先我們來看看start_kernel是如何初始化系統的, start_kerne定義在init/main.c?v=4.7, line 479 其程式碼很複雜, 我們只截取出其中與記憶體管理初始化相關的部分, 如下所示 table th:nth-of-type(1){