简体   繁体   中英

UIView removeFromSuperview causes app to crash

Let me explain my problem. I have 3 UIView : a LoginView , LibraryView , and a StoreView . I have this code to switch from one UIView to another:

- (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];
}

}

Basically, that is how I initialize the UIViews. And here are the buttons used to switch between them:

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

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

  //so on...

The problem arises when the I call the function libraryViewToLoginView and storeViewToLoginView . The app crashes whenever I call these functions, which is weird because the two functions worked properly before. I checked Profile and it gave me this stack trace:

#   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*>*)

As you can see, it is a bunch of calls on the CALayer which I don't really understand. I want to understand why is this happening. Can anyone explain?

Frankly I have not understood everything that you want to achieve here. But you should consider the sequence of events. See my comments:

  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. 

Well, it may even work as those statmens are next to each other. And when you remove it from its super view it gets released again. And there your app might crash.

BTW, without having it retained you should not release it at all. Or am I wrong here? However, addSubview should retain it and removeFromSuperview will release it, so no additional release would be required. Onece removed it should be gone. (If not retained somewhere else)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM