簡體   English   中英

內存管理

[英]Memory Management

方法removeFromSuperView如何工作? 我想重新初始化視圖時遇到內存訪問錯誤的問題

- (id)init {
   if (!(self = [super init]))
      return nil;

   _mainView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 
   NSLog(@"retainCount :%d", [_mainView retainCount]);
   UIButton *reInitButton = [[UIButton alloc] initWithFrame:CGRectMake(0.0f,0.0f,90.0f,35.0f)];      
   [reInitButton addTarget:self action:@selector(buttonDidTapped:) forControlEvents:UIControlEventTouchUpInside];
   [[self view] addSubView:_mainView];
   NSLog(@"retainCount :%d", [_mainView retainCount]);
   [_mainView release];
   NSLog(@"retainCount :%d", [_mainView retainCount]);

   return self;
}

- (void)buttonDidTapped:(id)sender {
   [_mainView removeFromSuperView]; //crash during second times press the button
   NSLog(@"retainCount :%d", [_mainView retainCount]);
   _mainView = [[UIView alloc] initWithFrame[[UIScreen mainScreen] bounds]];
   [[self view] addSubView:_mainView];
   NSLog(@"retainCount :%d", [_mainView retainCount]);
   [_mainView release];
   NSLog(@"retainCount :%d", [_mainView retainCount]);
}

每當有任何保留或分配或釋放關鍵字時,我都有NSLog。 結果非常奇怪。

//init
retainCount : 1
retainCount : 2
retainCount : 1
//1st time pressed button
retainCount : 1 //remove super view didn't decrease
retainCount : 2
retainCount : 1
//2nd time pressed button
retainCount : 0 //crash. Memory bad access

奇怪的是為什么它在第一次按下時沒有崩潰?

切勿使用RETAINCOUNT 很抱歉將其設置為大寫,但我無法弄清楚為什么人們仍然使用它。 這是內存管理的錯誤參考。 請改用樂器或類似工具。

我認為您的問題在這里:

[_mainView release];

您已經刪除了對_mainView的引用,但是,根據我的閱讀,這是一個成員變量,您將保留它並繼續調用方法。 那是無效的。 調用-release ,您實際上已經告訴系統不再使用該對象,並且對於指向該對象的陳舊指針,您將無法做任何有用的事情,就像調用-removeFromSuperView-removeFromSuperView稍后。

如果要繼續保留_mainView並在其上調用代碼,則需要保留引用。 也許您應該將發行版移至對象的-dealloc方法。 或者,您可以在按鈕方法中-release它,並在下次需要時重新創建一個新視圖。

作為一個有用的技巧,許多程序員喜歡在釋放對象后將對象重置為NULL (或者在objC語言中為nil ),以提醒您不能再次使用該對象。 如果您-release某物,則最好做到這一點。

最后,我建議您使用Google的“引用計數”一詞,並仔細閱讀; NSObject的細節相比,它是一個更通用的習慣用法,考慮基礎知識以及如何用另一種語言(例如C)實現這一點很有用。這將幫助您更好地推理引用計數對象。

_mainView您不應該訪問_mainView 這可能很難解釋,所以請忍受。 我們要計算的不是對象的絕對保留數,而是絕對保留數。

您為對象分配內存,並使用_mainView指向該對象:

_mainView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

您對該對象有1個所有權聲明。 當您將其添加為另一個視圖的子視圖時,該視圖同樣會聲明所有權,但這不是您的,而是視圖的所有權。 它使_mainView的對象粘住的事實是偶然的,因此您不應該依賴它。 然后釋放對象:

[_mainView release];

您已放棄所有權聲明-您現在擁有0個聲明,並且您不應再嘗試訪問此對象。 你不擁有它。 同樣,由於另一個視圖正在使用它而仍然存在它的事實,以及您仍然有指向它的指針的事實是偶然事件*,您不應依賴它們。

是時候處理按鈕按下了,您正在訪問一個沒有所有權的對象:

[_mainView removeFromSuperView];

這會導致崩潰,這是無法預料的,​​但這並非不合理。 通過將您的所有權聲明設為0,您告訴系統“我不再需要該對象。在此之后,我將不再訪問它。如果它消失了,我將不會受到影響。” 但是,實際上,您確實需要它保持存在,並且需要訪問它。

然后,您應該做的是移動這行:

[_mainView release];

到按鈕動作內部, removeFromSuperview在調用removeFromSuperview


*通過設置_mainView = nil;可以避免第二種情況_mainView = nil; 在這種情況下,將其釋放后,就無法解決更大的問題。

暫無
暫無

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

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