【问题标题】:ViewDidLoad and UINavigationController in iOS?iOS 中的 ViewDidLoad 和 UINavigationController?
【发布时间】:2012-06-22 22:29:37
【问题描述】:

我有一个基于UINavigationController 的应用程序。有一个带有按钮的菜单屏幕(推送到导航控制器堆栈)到其他 9 个“子屏幕”之一。这些子屏幕都没有与任何其他屏幕相连。当用户在“子屏幕”上完成输入数据时,他们可以按下完成按钮,该按钮将弹回原始菜单屏幕。 (如果您难以想象这一点,请想象一棵像故事板一样的树,其中有一个根 ViewController,然后是 9 个叶 ViewController)。

好的,对于这个设置,我有几个关于 viewDidLoad 工作原理的问题。

~ 首先,viewDidLoad 应该在我们每次转换到子屏幕时被调用。例如,假设我从菜单屏幕转到子屏幕“B”,然后返回菜单屏幕,然后返回子屏幕“B”。 B 的viewDidLoad 方法应该被调用两次吗?如果没有,为什么我的会被调用两次?

~ 其次,假设每次都会调用它,如果我有很多长的操作需要为每个子屏幕执行一次,我该怎么办?我应该把它们放在哪里(如果我把它们放在viewDidLoad 中,如果用户一直在这个页面和菜单之间来回切换会发生多次)?

【问题讨论】:

    标签: objective-c ios xcode model-view-controller


    【解决方案1】:

    回答您的问题:

    1. 是的,通常 B 的 viewDidLoad 方法应该在每次被压入 UINavigationController 的堆栈时被调用。这是因为每次将 B 从堆栈中弹出时,它通常都会被释放,而每次您转到 B 时,都会创建一个 B 的新实例。

    2. 有很多方法可以处理这种情况。如果不确切地了解您正在尝试做什么,就很难说出什么适合您。一种方法是创建一个处理处理的singleton object。这可能比在 UIViewController 中处理它更好的原因是单例可以在应用程序的整个生命周期中存在,而 UIViewControllers 通常具有相对较短的生命周期。单例对象可以只创建一次,它们可以管理您需要在应用程序的整个生命周期中持久保存的任何操作和数据。

    【讨论】:

    • viewDidLoad 只会在每次视图被“初始化”时被调用一次,而不是每次被添加到堆栈中时
    • 我在回复中解释说“每次将 B 从堆栈中弹出时,它通常会被释放,并且每次您转到 B 时都会创建一个新的 B 实例”,即 init/viewDidLoad每次访问 B 时都会调用。
    • 我不会说它通常会发布。 viewDidUnload 仅在视图属性被释放/设置为 nil 时在视图控制器上调用,这通常仅在应用收到内存警告时发生。
    • 如果您确保保留对您的 viewController 的引用,它不会被释放,因此您可以重用它。如果视图加载时间较长,不建议每次都释放它。
    • 首先每个人都在这里做了很多假设。有没有人问过他是否重复初始化?如果是这种情况,那么每次都会调用它。其次,@Michael Frederick 是对的,当导航控制器弹出视图控制器时,它确实被释放了,因此“可能”需要创建一个新实例并将其分配给该指针。直到他通过初始化该视图控制器来回答关于他将如何进行的问题之前,一切都是纯粹的假设。在试图对人苛刻和扣分之前,应该做好记录。
    【解决方案2】:

    viewWillAppear 每次视图出现时都会被调用。 viewDidLoad 仅在构造视图时被调用 - 例如在视图控制器 initFromNibNamed 调用视图被访问之后。每当您的视图控制器不在视图中但进入视图时,就会调用viewWillAppear - 因此当您的视图控制器被推送时,会调用viewWillAppear。所以你可能认为你的viewDidLoad 被调用了两次,但实际上它可能不是。所以你应该把方法放在viewDidLoad。你在做什么需要很长时间?

    【讨论】:

      【解决方案3】:

      1。 viewDidLoad 在视图加载时调用,viewWillAppear 在视图可见时调用。

      如果您的 viewDidLoad 被多次调用,这意味着您每次显示视图时都在加载视图,每次弹出视图时都会释放它。如果您发布一些代码,我可以帮助您更好地识别问题。

      你可以这样做:

      在您的“根”viewController 类中,将每个“叶子”ViewController 声明为成员,假设它们被称为leafController1、leafController2 等,并为它们创建保留属性。

      @interface YourRootViewController : UIViewController {
          LeafController1Class *leafController1;
          LeafController2Class *leafController2;
          // ...
      }
      
      @property (nonatomic, retain) LeafController1Class *leafController1;
      @property (nonatomic, retain) LeafController2Class *leafController2;
      
      // ...
      
      @end
      

      在您的顶级 ViewController 的 ViewDidLoad 中,使用“initWithNibName”等(或您正在执行的任何创建它们的操作)初始化所有叶控制器。像这样保留他们的实例:

      self.leafController1 = [[[LeafController1Class alloc] initWithNibName:@"LeafController1NibName" bundle:nil] autorelease];
      

      当用户按下按钮时,将正确的叶子推送到导航控制器:

      [myNavigationController pushViewController:leafController1 animated:YES];
      

      当您现在弹出叶控制器时,它们将保留在内存中,因为您保留了它们。 这样,只要您始终将视图控制器的相同实例推送到导航控制器,您的 viewDidLoad 只会为每个叶子调用一次。

      2。 与视图相关的繁重代码应在视图已加载时执行,即由 viewDidLoad 触发。但是,保留其他保存有关您的应用程序信息的类可能是一个好主意,这些类不是视图控制器并且与 UI 分开。繁重的计算最好在后台进行,或者在应用第一次加载时进行。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-04-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-06
        相关资源
        最近更新 更多