2013-02-11 175 views
0

讓我解釋我的問題。我有3 UIView:a LoginView,LibraryViewStoreView。我有此代碼切換從一個UIView的另一:UIView removeFromSuperview導致應用程序崩潰

- (void)showView:(NSInteger)viewTag 
{ 
    if (viewTag == 1) 
    { 
     if (self.loginView) 
     { 
     self.loginView = nil; 
     self.loginView.delegate = nil; 
     } 

     LoginView *loginPage = [[LoginView alloc]initWithFrame:self.view.bounds]; 
     [loginPage setDelegate:self]; 

     self.loginView = loginPage; 

     [loginPage release]; 

     [self.view addSubview:self.loginView]; 
} 
else if(viewTag == 2) 
{ 
    if (self.libraryView) 
    { 
     self.libraryView = nil; 
     self.libraryView.delegate = nil; 
    } 

    LibraryView *libraryPage = [[LibraryView alloc]initWithFrame:self.view.bounds]; 
    [libraryPage setDelegate:self]; 

    self.libraryView = libraryPage; 

    [libraryPage release]; 

    [self.view addSubview:self.libraryView]; 
} 
else 
{ 
    if (self.bookStoreView) 
    { 
     self.bookStoreView = nil; 
     self.bookStoreView.delegate = nil; 
    } 

    BookStoreView *bookStore = [[BookStoreView alloc]initWithFrame:self.view.bounds]; 
    [bookStore setDelegate:self]; 

    self.bookStoreView = bookStore; 

    [bookStore release]; 

    [self.view addSubview:self.bookStoreView]; 
} 

}

基本上,這是我如何初始化UIViews。這裏是用於它們之間進行切換的按鈕:當我調用函數libraryViewToLoginViewstoreViewToLoginView

- (void)loginViewToLibraryView 
    { 
    [self.loginView removeFromSuperview]; 
    [self showView:2]; 
    } 

- (void)libraryViewToStoreView 
    { 
    [self.libraryView removeFromSuperview]; 
    [self showView:3]; 
    } 

    //so on... 

,就會出現問題。每當我調用這些函數時,該應用程序都會崩潰,這很奇怪,因爲這兩個函數之前都能正常工作。我查了一下資料,它給了我這個堆棧跟蹤:

# Address  Category Event RefCt Timestamp Size Responsible Library Responsible Caller 
0 0xc4dcac0 CALayer Malloc 1 00:02.233.004 48 UIKit     -[UIView _createLayerWithFrame:] 
1 0xc4dcac0 CALayer Retain 3 00:02.238.317 0 QuartzCore    CA::Layer::insert_sublayer(CA::Transaction*, CALayer*, unsigned long) 
2 0xc4dcac0 CALayer Release 2 00:02.238.324 0 UIKit     -[UIView(Internal) _addSubview:positioned:relativeTo:] 
3 0xc4dcac0 CALayer Retain 3 00:02.238.518 0 QuartzCore   -[CALayerArray copyWithZone:] 
4 0xc4dcac0 CALayer Release 2 00:02.238.602 0 UIKit     -[UIView(Hierarchy) _makeSubtreePerformSelector:withObject:withObject:copySublayers:] 
5 0xc4dcac0 CALayer Retain 3 00:02.238.665 0 QuartzCore   -[CALayerArray copyWithZone:] 
6 0xc4dcac0 CALayer Release 2 00:02.238.796 0 UIKit     -[UIView(Internal) _didMoveFromWindow:toWindow:] 
7 0xc4dcac0 CALayer Retain 3 00:05.107.397 0 QuartzCore   -[CALayerArray copyWithZone:] 
8 0xc4dcac0 CALayer Release 2 00:05.107.539 0 UIKit     -[UIView(Hierarchy) _makeSubtreePerformSelector:withObject:withObject:copySublayers:] 
9 0xc4dcac0 CALayer Retain 3 00:05.107.613 0 QuartzCore   -[CALayerArray copyWithZone:] 
10 0xc4dcac0 CALayer Release 2 00:05.107.700 0 UIKit     -[UIView(Internal) _didMoveFromWindow:toWindow:] 
11 0xc4dcac0 CALayer Retain 2 00:06.105.958 0 QuartzCore   -[CALayerArray copyWithZone:] 
12 0xc4dcac0 CALayer Release 2 00:06.108.134 0 UIKit     -[UIView dealloc] 
13 0xc4dcac0 CALayer Release 1 00:06.108.492 0 UIKit     -[UIView dealloc] 
14 0xc4dcac0 CALayer Zombie -1 00:06.115.332 0 QuartzCore   CA::release_objects(X::List<void const*>*) 

正如你所看到的,它是一堆的CALayer的電話,我真的不明白的。我想明白爲什麼會發生這種情況。誰能解釋一下?

+0

你有一個殭屍進程=你釋放重新分配的對象。嘗試使用儀器來分析內存泄漏。向我們展示@property的loginView和libraryView,他們強大/保留? – mientus 2013-02-11 12:01:10

+0

您是否嘗試在將它們添加爲子視圖後發佈最近創建的視圖?我對pre-ARC obj c不是很熟悉,但是,爲視圖添加子視圖會創建新的強引用,因此您可以交換這些行(以及類似的行): [bookStore release]; [self.view addSubview:self.bookStoreView]; – guenis 2013-02-11 12:01:15

+0

我只想知道'loginView','libraryView'和'bookStoreView'是否有保留屬性? – Ilanchezhian 2013-02-11 12:01:37

回答

0

坦白說,我不明白,你想在這裏實現的一切。但是你應該考慮事件的順序。看我的評論:

if (self.loginView) 
    { 
    self.loginView = nil; 
    //self.loginView is nil now. What so you think doese happen on the next line? 
    self.loginView.delegate = nil; 
    // change the sequence of this lines and it will be ok. 
    } 

    LoginView *loginPage = [[LoginView alloc]initWithFrame:self.view.bounds]; 
    [loginPage setDelegate:self]; 

    self.loginView = loginPage; 

    [loginPage release]; //here you release the object. it is gone now. However, there are still references to it. 

    [self.view addSubview:self.loginView]; // here you add the released object. What do you expect to happen? 
    // Switch those two statmetns and you should be fine. 

那麼,它可能甚至工作,因爲這些statmens是彼此相鄰。當你從超級視圖中刪除它時,它會再次被釋放。那裏你的應用程序可能會崩潰。

BTW,而不必它保留你不應該釋放它。還是我在這裏錯了?但是,addSubview應該保留它,removeFromSuperview將會釋放它,所以不需要額外的發佈。 Onece移除它應該消失。 (如果不保留別的地方)

+0

感謝您的迴應!儘管如此,我並沒有完全理解它。我從另一位程序員那裏繼承了它,我仍然在學習這個流程。所以謝謝你幫助我!如果有效,我會接受你的回答。 – 2013-02-11 12:38:42

+0

好的。那是舊的代碼呢?這就是爲什麼你不使用自動引用計數?對於新項目,您應該考慮使用它。記憶管理造成的很多痛苦都消失了。 – 2013-02-11 20:17:05

+0

是的。我試圖用Xcode中的Refactor將它轉換爲ARC,但有些說它有些東西阻止它轉換。我沒有太多時間去找那些只是爲了轉換成ARC的東西,所以我決定現在就離開它。 – 2013-02-12 00:55:12