簡體   English   中英

Objective-C中的屬性

[英]Property in Objective-C

Line 1: First.h
Line 2: @property (nonatomic, retain) NSString *name;

Line  3: First.m
Line  4: @synthesize name;
Line  5: -(void)viewDidLoad()
Line  6: {
Line  7:     name = [NSString stringWithString:@"Hello"];
Line  8:                          OR
Line  9:     self.name = [[NSString alloc]initWithString:@"Hello"]; 
Line 10:                          OR
Line 11:  }
Line 12:-(void)dealloc()
Line 13: {
Line 14: [name release];
Line 14: } 

問題1:
如果遵循第7行,則一切正常,如果使用第9行,則存在內存泄漏。 據我所知,self是指向當前對象的,如果我使用self.object或只是object不再有任何區別。

問題2:如果我用過

@synthesize name = _name;

那么,哪個用於設置name的值,哪個用於獲取name的值? 之間的區別:

name = [NSString stringWithString:@"Hello"];
            OR
self.name = [NSString stringWithString:@"Hello"];
            OR
_name = [NSString stringWithString:@"Hello"];

問題3:
如果我創建任何屬性,那么在分配顯示內存泄漏時是否有必要在內存中分配內存?

要回答第一個問題 :之所以泄漏,是因為使用alloc方法初始化字符串時,您將保留創建的對象,但是之后不釋放該對象,因此會泄漏,而使用stringWithString創建字符串時,會得到一個由自動釋放池自動釋放的自動釋放對象。 請注意,在第9行的示例中,您正在初始化對象並將其傳遞給屬性的setter,如果使用了ivar,情況將會有所不同。

回答第二個問題 :您正在合成屬性名稱,並將其與名為_name的內部變量(ivar)關聯,因此在您的類內部,您可以使用ivar _name訪問屬性的值。

我強烈建議閱讀有關內存管理Apple文檔

問題1:如果我遵循第7行,那么一切都很好,如果我使用了第9行,則存在內存泄漏。 據我所知,self是指向當前對象的,如果我使用self.object或只是對象,則不再有任何區別。

Line  7:     name = [NSString stringWithString:@"Hello"];
Line  8:                          OR
Line  9:     self.name = [[NSString alloc]initWithString:@"Hello"]; 

在第7行,您使用了一個便捷構造函數,該構造函數返回一個自動釋放的對象,並將該對象直接分配給您的name ivar; 現在,可以將一個自動釋放的對象分配給一個保留屬性,但是將一個自動釋放的對象直接分配給一個ivar而不顯式地保留它是不正確的:

name = [[NSString stringWithString:@"Hello"] retain];

在第9行上,您使用的是alloc / init,它為您提供了一個保留對象:將這樣的對象直接分配給ivar是正確的,但是在分配給keep屬性之前,您應該自動釋放它,例如:

self.name = [[[NSString alloc]initWithString:@"Hello"] autorelease]; 

您可以根據對象保留數對此進行推理:

  1. 便利構造函數將保留計數設置為1,但是稍后框架會通過release調用將其自動減少;

  2. alloc / init將為您提供保留計數1,除非您明確調用release ,否則保留計數不會減少;

  3. 當對象保留計數變為0時,它將被釋放。

根據保留計數進行推理只是一種查看內存管理整個問題並了解框架深層內容的方法。 但是,在任何情況下,這都不是分析對象生命周期的正確方法。

那么哪個用於設置name的值,哪個用於獲取name的值? name = [NSString stringWithString:@"Hello"];之間的區別name = [NSString stringWithString:@"Hello"]; self.name = [NSString stringWithString:@"Hello"]; _name = [NSString stringWithString:@"Hello"];

name = [NSString stringWithString:@"Hello"];

_name = [NSString stringWithString:@"Hello"];

在兩種情況下都是一樣的。 這將繞過屬性setter(/ getter)方法,並直接分配給ivar。 在這種情況下,您的應用遲早會崩潰,因為您是直接將自動釋放的對象分配給ivar。 這是正確的:

_name = [[NSString stringWithString:@"Hello"] retain];

要么

_name = [[NSString alloc] initWithString:@"Hello"];

請注意,在將ivar聲明為_name的程序中,不能使用name來引用它。 如果聲明屬性而沒有像問題1一樣顯式指定ivar,則可以使用name直接引用ivar(在這種情況下, name是編譯器自動為您生成的ivar)。

另一方面:

self.name = [NSString stringWithString:@"Hello"]; 

將使用屬性訪問器方法(實際上是setter); 由於您的屬性被聲明為retain ,因此可以將便利構造函數stringWithString:返回的自動釋放變量分配給它。

問題3:如果我創建任何屬性,那么在分配內存時就需要在內存中進行分配。

這對我來說真的不是很清楚。

可以閱讀有關內存管理基礎知識的一個很好的文檔是: 內存管理策略以及Apple的《高級內存管理編程指南》中的實用內存管理

首先介紹一些背景知識, 概述MRC的概念:

內存管理與所有權有關。 只要您擁有一個對象,該對象就會存在,在您放棄所有權后的一段時間內,該對象將被銷毀。 您維護的對對象的任何引用實際上都是無效的,並且一旦放棄所有權就不應再使用。

所有權不是排他性的,而是遵循共享模型的,在任何給定時間可以有多個所有者,並且只有當對象沒有所有者時,它才可以被銷毀。

如果您只需要臨時使用一個對象,例如在單個代碼塊中,則不必總是擁有所有權。 部分原因是所有權和放棄方式的結果; 而不是立即放棄所有權,您可以請求稍后放棄所有權。

后來發生在一個應用程序的執行的某些點,除非手動添加任何這樣的點有每個周期通過運行循環執行一個這樣的點是。

通過retain調用或調用返回您擁有的對象的方法來聲明所有權 ,該對象通常是alloc ,但也可以是copy和其他對象。 使用release請求放棄所有權; 稍后通過調用autorelease

問題1:

Line  7:     name = [NSString stringWithString:@"Hello"];
Line  8:                          OR
Line  9:     self.name = [[NSString alloc] initWithString:@"Hello"]; 

第7行的右側(RHS)返回對您擁有的對象的引用。 左側(LHS)將此引用分配給實例變量 name 現在,您已經存儲了對您不擁有的東西的引用, 這很不好,因為在將來的任何時候,對象的所有者可能會放棄所有權,該對象被破壞,並且name引用無效。 課程:*不要將對您不擁有的對象的引用存儲在實例變量中”。

另一方面,第9行的RHS返回對您擁有的對象的引用。 但是,LHS使用屬性調用 self.name來存儲引用,並且它還擁有所有權,因為它是retain屬性-您現在擁有它兩次, 這很不好,但是如果使用另一種方式; 除非您也兩次放棄所有權(您可能不會這樣做),否則該對象將始終具有所有者並且將永遠存在,通常稱為泄漏

如果交換代碼:

Line  7a:     name = [[NSString alloc] initWithString:@"Hello"];
Line  8a:                          OR
Line  9b:     self.name = [NSString stringWithString: @"Hello"]; 

然后它將完成您的期望。 第7a行的RHS返回您擁有的對象引用,LHS將其存儲在實例變量 name ,該實例變量 name屬性 name管理。

第9a行的RHS返回您不擁有的對象引用,但是LHS使用屬性調用,並且由於該屬性具有retain屬性所有權,並且實例變量 name存儲的引用是對擁有對象的引用。

無論哪種情況,當當前實例( self )被銷毀時,屬性name具有實例變量name引用的任何對象引用的retain屬性所有權,則將被放棄。

問題2

使用有什么影響:

@synthesize name = _name;

這僅意味着屬性 name將使用實例變量 _name而不是name 在您的代碼段中,您永遠不會聲明name_name因此兩者都由@synthesize自動聲明; 因此,取決於@synthesize只有name實例name_name實例變量。 因此,問題2的答案就是問題1的答案,每個實例變量name引用都由_name替換。

問題3

如果我理解此問題,但不確定我是否知道,那么問題1的答案將涵蓋該問題。

高溫超導

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM