【问题标题】:How to properly release and switch views in multiview controller?如何在多视图控制器中正确释放和切换视图?
【发布时间】:2010-07-15 03:30:57
【问题描述】:

我正在尝试为游戏创建一个多视图控制器,其中一个根视图控制器在切换到另一个视图之前释放视图。反过来,子视图控制器本身就是子根视图控制器,因为它们包含其他视图控制器。

例如,我的 singlePlayerViewController 将有一个shakeObjectViewController 可能还有其他。使用操作表在视图之间切换,将应用程序委托作为操作表的委托,从 singlePlayer 视图切换到另一个视图时,一切都按预期工作。

但是当我尝试使用相同的 init 方法创建一个新的 singlePlayerViewController 时,当我尝试插入一个子视图(即shakeObjectViewController.view)时,调试器会抛出一个 EXC_BAD_ACCESS 错误。

目前的初始化是这样的: 应用委托使用默认的 init 方法初始化窗口,

- (void)applicationDidFinishLaunching:(UIApplication *)application {   
    // Override point for customization after application launch
   [window addSubview:rootViewController.view];
    [window makeKeyAndVisible];
}

然后在rootViewController.m的viewDidLoad中,

   if(singlePlayerViewController == nil) {

      SinglePlayerViewController *singleController = [[SinglePlayerViewController alloc]
                                       initWithNibName:@"SinglePlayerView" bundle:nil];
      self.singlePlayerViewController = singleController;
      [singleController release];
   }

   [self.view insertSubview:singlePlayerViewController.view atIndex:0];

后跟 singlePlayerViewController.m,

- (void)viewDidLoad {
   self.view.tag = kSinglePlayerView; // tag the view

   ShakeObjectViewController *shakeController = [[ShakeObjectViewController alloc]
                                       initWithNibName:@"ShakeObjectView" bundle:nil];
   self.shakeObjectViewController = shakeController;
   self.view = shakeController.view;
   [shakeController release];
}

请注意我的 singlePlayerViewController 没有插入子视图,而是用子视图控制器的视图替换它自己的视图。 (不知道这是否是一个好习惯:?:)

当切换视图时,应用代理执行以下操作:

for(UIView *subview in [rootViewController.view subviews])
{   
   [subview removeFromSuperview];
}
[rootViewController.singlePlayerViewController release]

[rootViewController initMultiplayerView];

然后在切换回单人模式时,执行rootViewController.m的viewDidLoad中同样的init方法,调试器在“[self.view insertSubview:singlePlayerViewController.view atIndex:0];”上抛出错误行。

关于为什么没有创建新视图的任何想法?我尝试将 singlePlayerViewController 设置为 nil 而不是释放,但随后在“self.view = shakeController.view;”上抛出错误线。 我的理解是,如果视图属性当前为 nil,则在下次访问视图时会自动为您创建一个新属性。

initWithNibName 是否只意味着执行一次?还是我的设计方式在 # 视图控制器方面过于复杂?

【问题讨论】:

    标签: iphone cocoa-touch


    【解决方案1】:

    请注意我的 singlePlayerViewController 没有插入子视图,而是用子视图控制器的视图替换它自己的视图。 (不知道这是否是一个好习惯:?:)

    这里有巨大的警告标志。听起来您有一个带有两个视图控制器的视图。这是不好的。

    考虑插入和删除子视图:

    • 根视图
      • SinglePlayerView(可移除并替换为 MutliplayerView)
        • ShakeView

    这样你就有了 3 个视图和 3 个视图控制器。

    这是框架的使用方式。

    【讨论】:

      【解决方案2】:

      您的设计确实有点过于复杂,但这并不意味着调试器应该抛出随机错误! :) 不过,尝试简化它可能会有所帮助。如果您只是要立即将其替换为摇动对象视图,我不明白您为什么需要单个播放器视图。

      我绝对认为你想将 singlePlayerViewController 设置为 nil,因为否则 rootViewControllers viewDidLoad 方法中的“if(singlePlayerViewController == nil) {”行将为 false,并且不会创建新的视图控制器,这就是为什么你得到第一个错误。

      我只看到 3 种方式会导致“self.view = shakeController.view”行出现访问错误:

      • shakeController 不是零,而是垃圾。这似乎不太可能,因为它刚刚被初始化,除非它的 viewDidLoad 释放自己或类似的东西。
      • self 不是 nil,而是垃圾。同样,不太可能,但可能 - 也许检查调试器以查看 self 的样子(它的变量是否有意义等)
      • 当您调用 self.view = ... 时,它将向原始视图发送释放。单人视图的dealloc方法中是否有可能导致访问错误的代码?

      self 或shakeController 为nil 不会导致错误,因为该行相当于

      [self setView:[shakeController view]]
      

      如果它们为 nil,则不会崩溃,因为允许向 nil 发送消息。

      【讨论】:

      • 单人视图最终会在其他视图之间切换,而不仅仅是摇动视图。尝试评论“if(singlePlayerViewController == nil)”行并无论如何实例化一个新控制器。同样的错误。 "NSLog(@"shake's view = %@",shakeController.view);",抛出同样的错误。
      • 还尝试完全跳过单人视图控制器并直接在根控制器中使用shakeObject VC。同样的错误。如果我不尝试释放它们,切换 btw 视图效果很好,但我每次都需要一个全新的视图。感谢您的回复。
      【解决方案3】:

      是的,所有标记为(非原子,保留)的@property 语句。

      也许这个问题可以重新表述为,如何多次从 nib 创建视图控制器?第二次创建 VC,不管释放之前的同一个类的 VC,关联的视图都没有创建,并抛出 BAD ACCESS 错误。

      【讨论】:

        【解决方案4】:

        你这样做的方式让我很困惑,我认为这对你的错误负责。我正在逐行查看它,并试图弄清楚它为什么会崩溃并且没有完全弄清楚,但同时我很难弄清楚切换期间视图发生了什么。

        我会按照 Kailoa 的建议用三个不同的视图控制器重写它。每个视图都应该有自己的控制器。视图不应该替换它自己,它应该被它的父视图控制器替换。

        我怀疑在她的某个地方有什么东西被释放了,然后发送了消息,然后你尝试用返回的消息做某事,认为某物是一个对象,而实际上它不是。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2016-11-16
          • 2014-05-10
          • 2012-04-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多