0

私の問題を説明しましょう。LoginViewLibraryView、およびStoreViewの3 つがUIViewあります。ある UIView から別の UIView に切り替えるには、次のコードがあります。

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

}

基本的に、それがUIViewを初期化する方法です。そして、それらを切り替えるために使用されるボタンは次のとおりです。

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

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

  //so on...

libraryViewToLoginViewI が関数andを呼び出すときに問題が発生しますstoreViewToLoginView。これらの関数を呼び出すたびにアプリがクラッシュします。以前は 2 つの関数が正常に機能していたため、これは奇妙です。プロファイルを確認したところ、次のスタック トレースが表示されました。

#   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 での一連の呼び出しで、よくわかりません。なぜこれが起こっているのか理解したい。誰でも説明できますか?

4

1 に答える 1

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. 

まあ、それらのスタメンが互いに隣り合っているので、それはうまくいくかもしれません. スーパー ビューから削除すると、再び解放されます。そして、アプリがクラッシュする可能性があります。

ところで、それを保持せずに、まったく解放しないでください。それとも私はここで間違っていますか?ただし、addSubview はそれを保持し、removeFromSuperview はそれを解放する必要があるため、追加の解放は必要ありません。一度削除すると、それはなくなるはずです。(別の場所に保持されていない場合)

于 2013-02-11T12:09:10.453 に答える