2013-04-11 27 views
0

我正在深入內存管理,我發現這一點。將內存分配給屬性的潛在漏洞

我創建了一個屬性按鈕。

@property (nonatomic, retain) UIButton *button; 

在ViewdidLoad方法中,我寫了下面的代碼。

self.button = [[UIButton alloc] initwithFrame : CGRectMake(10, 10, 20, 20)]; 
[self.view addsubView:self.button]; 

做XCode分析,我得到了第33行分配變量的潛在泄漏,即: self.button。

爲什麼會發生這種情況?如果我創建一個本地UIButton並將其分配給self.button並使用它,則不存在潛在的泄漏。如果我將內存分配給self.button或任何屬性變量,它會泄漏。

感謝 Jithen

+0

只是爲了符合...用'strong' – 2013-04-11 04:47:21

+0

同樣的,強太多嘗試.. – Coder 2013-04-11 04:49:18

+0

ARC或MRC ???? – 2013-04-11 04:51:14

回答

2

值分配給self.button調用合成的setter方法:

- (void)setButton:(UIButton *)button; 

因爲你添加了「保留」屬性,你的財產申報,合成的setter會自動調用在所設置的對象上「保留」。這增加了對象的保留計數。

在UIButton上調用「alloc」還會提升對象的保留計數。

所以做self.button = [UIButton alloc]基本上會使您的保留計數增加2。這就是爲什麼會有潛在的泄漏。

你可以做任何解決這個問題:

self.button = [[[UIButton alloc] initwithFrame : CGRectMake(10, 10, 20, 20)] autorelease]; 

UIButton *temp = [[UIButton alloc] initwithFrame : CGRectMake(10, 10, 20, 20)]; 
self.button = temp; 
[temp release]; 

_button = [[UIButton alloc] initwithFrame : CGRectMake(10, 10, 20, 20)]; 
+0

所以,如果我使用保留屬性,其保留計數將自動爲1。 – Coder 2013-04-11 04:54:33

+0

如果您使用retain屬性,那麼無論何時使用「self.button =」或「[self setButton:]」設置該屬性,您將其設置的對象的保留計數值都會加1. – nebs 2013-04-11 04:56:19

+0

感謝您的詳細交代。但我試圖刪除保留屬性,並嘗試與分配。分配屬性不應增加執行self.button =時的保留計數。但即使在這裏,它也在泄漏潛在的泄漏。 – Coder 2013-04-11 04:57:45

2

@property (nonatomic, retain) UIButton *button;使用這個你保留對象。

現在使用self.button = [[UIButton alloc] initwithFrame : CGRectMake(10, 10, 20, 20)];你分配內存,並保留計數增加1

所以在你情況下,這是一個泄漏的保留對象的數量增加。如果你有本地對象,你分配然後再次釋放它。所以沒有額外的保留計數並且沒有泄漏。

Abstarct

當您使用工廠方法或使用ALLOC,新創建對象,保留,複製,mutableCopy你的對象有+1每次保留計數。你在這種情況下擁有對象。你有責任釋放它。所以你需要版本對象完成後使用對象,導致-1保留計數對象。

編輯

現在你正在做

@property (nonatomic, assign) UIButton *button; 
self.button = [[UIButton alloc] init]; 
[self.button release]; 

在這裏,您使用的是自它調用您創建的屬性變量的訪問對象。你發送+1保留計數超過屬性對象,所以它變成了2,因爲它自己擁有getter和setter屬性。所以不要這樣做,你可以使用像這樣的實例變量。

@property (nonatomic, assign) UIButton *button; 
_button = [[UIButton alloc] init]; 
[_button release]; 
+0

感謝您的解釋。如果我嘗試分配而不是保留,我會發生潛在的泄漏。但它不應該。不是嗎。 – Coder 2013-04-11 05:00:34

+0

如果你使用assign並且仍然分配了你的對象,那麼這是一個泄漏,因爲你還沒有釋放它。 – 2013-04-11 05:11:17

+0

@property(nonatomic,assign)UIButton * button;在分配內存給self.button = [[UIButton alloc] init]之後;我釋放[self.button發佈]。即使那麼它是投擲潛在的泄漏.. – Coder 2013-04-11 05:15:10

1

ARC之前,你通常會做這樣的retain變量:

UIButton* btn = [[UIButton alloc] initwithFrame : CGRectMake(10, 10, 20, 20)]; 
self.button = btn; // property increases retain count because of its declaration as "retain" 
[btn release]; 

與ARC,你可能會做這樣的:

@property (nonatomic, weak) UIButton* button; 

self.button = [[UIButton alloc] initwithFrame : CGRectMake(10, 10, 20, 20)]; 
[self.view addsubView:self.button]; 

第二個例子說明你不真的不需要讓你的財產保留按鈕(通過retainstrong),因爲當你添加一個子視圖到視圖容器時,包含的視圖將會重新t新的孩子。

當然,也有一些例外。有時,您可能實際上想要從超級視圖中刪除您的視圖(按鈕),但不會釋放它,因爲您稍後會將其添加回來。

所以,有時候,保留UI對象是有效的。通常情況下,這不是必需的。

更新:我想在這裏發表意見,這種問題的是,爲什麼蘋果希望人們使用ARC。這是一個非常基本的內存管理方案,它繼續爲許多新開發人員打下基礎。在這一點上,開始iOS開發者而不是的使用ARC的原因很少。

1

您的UIButton實例正在保留兩次。 [UIButton alloc]創建保留的實例,button屬性在通過self.button分配時保留它。使用MRC(手動引用計數)代碼,您需要釋放您保留的任何內容。

當您創建按鈕執行以下操作:

UIButton *button = [[[UIButton alloc] initWithFrame:...] autorelease]; 
self.button = button; 

另外,使用首選的創建者方法`的UIButton':

self.button [UIButton buttonWithType:UIButtonTypeCustom]; 
self.button.frame = CGRectMake(...); 

你還需要,無論你清理釋放按鈕分配給您的屬性的對象。如果您使用ARC(自動引用計數)而不是MRC,則編碼將會簡單得多。

0

我不知道你是否已經釋放它,但每當我們分配內存時,我們必須釋放它(如果你的項目中沒有使用ARC)。 所以才釋放它的dealloc中像這樣:

-(void)dealloc { 
    [button release]; 
    [super dealloc]; 
}