【问题标题】:Do I programmatically add SubViews in ViewDidAppear, ViewDidLoad, ViewWillAppear, the constructor?我是否以编程方式在 ViewDidAppear、ViewDidLoad、ViewWillAppear、构造函数中添加子视图?
【发布时间】:2010-02-17 12:11:20
【问题描述】:

我试图从 Apple 的 sketchy 文档中找出哪种方法是初始化并将我的 Views 控件添加到控制器视图的最佳位置。

使用 winforms 相当简单,因为它们总是在 InitializeDesigner 中初始化,在构造函数中调用。如果可能,我正在尝试匹配此模式的可靠性。

我大部分时间都在 UINavigationController 中使用 UIViewControllersUITableViewControllers - 如果这会影响到这一切的话。

这是一个例子:

public MyController()
{
    // Here?
    AddViews();
}

public override ViewDidLoad()
{
    base.ViewDidLoad();

    // Or is should it be here?
    AddViews();
}

public override ViewWillAppear(bool )
{
    base.ViewWillAppear(animated);

    // Here?
    AddViews();
}

public override ViewDidAppear(bool animated)
{
    base.ViewDidLoad(animated);

    // Or maybe here?
    AddViews();
}

void AddViews()
{
    UILabel label = new UILabel();
    label.Text = "Test";
    label.Frame = new RectangleF(100,100,100,26);
    View.AddSubView(label);

    UIWebView webview = new UIWebView();
    webview .Frame = new RectangleF(100,100,100,26);
    View.AddSubView(webview);
}

当我将一些 UIControls 添加到不同位置的视图时,我得到了混合结果。有时视觉滞后,有时网络视图隐藏在某个地方。

添加它们是否有一般规则要遵守?

【问题讨论】:

标签: iphone xamarin.ios viewdidload viewdidappear viewwillappear


【解决方案1】:

一般来说,我是这样做的:

  • ViewDidLoad - 每当我向应与视图一起出现的视图添加控件时,我立即将其放入 ViewDidLoad 方法中。基本上,只要将视图加载到内存中,就会调用此方法。因此,例如,如果我的视图是具有 3 个标签的表单,我将在此处添加标签;没有这些表单,视图将永远存在。

  • ViewWillAppear:我使用 ViewWillAppear 通常只是为了更新表单上的数据。因此,对于上面的示例,我将使用它来实际将域中的数据加载到表单中。 UIViews 的创建是相当昂贵的,你应该尽可能避免在 ViewWillAppear 方法上这样做,因为当它被调用时,这意味着 iPhone 已经准备好向用户显示 UIView,你在这里做的任何事情将以非常明显的方式影响性能(如动画延迟等)。

  • ViewDidAppear:最后,我使用 ViewDidAppear 启动新线程来处理需要很长时间才能执行的事情,例如执行 Web 服务调用以获取额外数据好消息是,因为视图已经存在并且正在显示给用户,所以您可以在获取数据时向用户显示一个很好的“等待”消息。

不过,您还可以使用其他技巧。假设您希望 UILabel 在表单加载后“飞入”表单。在这种情况下,我会在 ViewDidLoad 中将标签添加到表单中,但在视图区域之外有一个 Frame,然后在 ViewDidAppear 中我会制作动画以将其飞回视图中。

希望对你有帮助。

【讨论】:

  • 谢谢你已经清理了很多。我无法从这个问题的 LoadView 示例中添加任何内容:stackoverflow.com/questions/573958/… - 你曾经使用过这种方法吗?
  • 所以基本上 loadView 是 UIViewController 的一个方法(当你试图弄清楚这些事情时,请使用罗塞塔石碑 - tirania.org/tmp/rosetta.html)。框架会自动在控制器中调用这个方法来告诉它创建视图,然后 UIViewController 的默认实现会调用 ViewDidLoad。虽然您可以重写此方法(并确保在执行时调用基本方法),但就个人而言,我更喜欢只使用 viewWillLoad(在 loadView 之前调用)和 viewDidLoad(在之后调用)。
  • 我不同意你不应该这样称呼它;这取决于你想要的行为。如果你继承了一个 ViewController 并且想要使用父级创建的视图,那么是的,你需要显式调用 super.loadView。这取决于具体情况,但您不希望发生的事情是让您的超类创建视图,然后在重载时将其丢弃。
【解决方案2】:

嗯,Apple 的文档似乎很清楚,恕我直言。

如果您以编程方式创建自己的根视图(此特定控制器的视图层次结构的根视图),您应该在 -loadView 中创建它而不调用 super,并在完成后设置 view 属性。如果您的视图是从 nib 加载的,则不应触摸 -loadView

您将自定义子视图添加到视图控制器的视图或以其他方式在-viewDidLoad 中修改它。推荐的做法是在-viewDidLoad 中创建你的UILabel 和UIWebView,并在-viewDidUnload 中释放它们,如果你需要将它们的引用设置为nil,如果你需要将它们保留在ivars 中。

注意:-viewDidUnload 在 iOS 6 中已被弃用并且不再被调用,因为 UIViewController 不再在内存压力下清除其视图。

【讨论】:

  • 谢谢我错过了那个方法。但是,我仍然觉得我列出的方法提供的何时使用它们的信息非常有限。即使在 loadView 中,你被告知的只是 '如果你想对视图执行任何额外的初始化,请在 viewDidLoad 方法中这样做' - 你什么时候需要这个方法?
  • loadView 是从 NIB 加载视图层次结构的方法,或者如果没有要加载的 NIB,则只创建一个空的 UIView。您可能想要一个自定义视图而不是它,在这种情况下您将覆盖 loadView。例如,UITableViewController 会覆盖此方法来创建 UITableView。我经常发现自己对自己的 UIView 子类做同样的事情。
  • viewDidUnload 已弃用
  • @SargeBorsch 是的,答案太老了。谢谢,我更新了这个。
【解决方案3】:

viewDidLoad 与“MEMORY”相关,viewWillAppear/viewDidAppear 与“APPEARANCE”相关。视图控制器的视图(它是视图控制器视图的根视图)可以多次出现/消失,即使控制器的视图已经在内存中。

(当提到根视图时,我也指它的子视图,因为根视图引用了它的子视图(子视图),但从视图控制器的角度来看,它通常只知道根视图。对子视图的引用可以通过视图控制器的出口正常发生。)

当出现内存警告时,根视图本身可能会从内存中删除。视图控制器将确定何时是从内存中删除它们的最佳时间。

因此,您通常会在 viewDidLoad 中添加子视图,因为添加子视图意味着将它们添加到内存中。但是,如果您以编程方式创建所有视图(而不是从 nib 文件),则不会。如果是这种情况,那么您应该重写 loadView 方法,并创建一个根视图并在那里添加子视图,因此在这种情况下您可以省略 viewDidLoad 来添加子视图。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-12-11
    • 2013-05-27
    • 1970-01-01
    • 1970-01-01
    • 2012-01-20
    • 2018-05-27
    • 1970-01-01
    相关资源
    最近更新 更多