2013-02-11 176 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