Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/114.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 为什么呈现模态UIViewController会导致呈现控制器上的setNeedsLayout?_Ios_Cocoa Touch_Uiview_Uiviewcontroller_Autolayout - Fatal编程技术网

Ios 为什么呈现模态UIViewController会导致呈现控制器上的setNeedsLayout?

Ios 为什么呈现模态UIViewController会导致呈现控制器上的setNeedsLayout?,ios,cocoa-touch,uiview,uiviewcontroller,autolayout,Ios,Cocoa Touch,Uiview,Uiviewcontroller,Autolayout,显示和取消显示视图控制器都会提示显示视图布局其子视图和/或更新其约束。对于重视图层次结构,这会带来性能问题。再次-这是现有的、当前显示的视图。正在创建和显示的模式非常轻 无论我是否使用autolayout(如我的示例项目中所示),都会发生这种情况 我已经建立了一个近似我正在开发的应用程序。有一个水平滚动的主父控制器UIScrollView。将多个子控制器添加到父控制器,并将其视图添加到scrollview,并使用NSLayoutConstraints进行排列。每个子视图本身都有一个子视图,即一个

显示和取消显示视图控制器都会提示显示视图布局其子视图和/或更新其约束。对于重视图层次结构,这会带来性能问题。再次-这是现有的、当前显示的视图。正在创建和显示的模式非常轻

无论我是否使用autolayout(如我的示例项目中所示),都会发生这种情况

我已经建立了一个近似我正在开发的应用程序。有一个水平滚动的主父控制器
UIScrollView
。将多个子控制器添加到父控制器,并将其视图添加到scrollview,并使用
NSLayoutConstraint
s进行排列。每个子视图本身都有一个子视图,即一个简单的
UIView
,也带有约束

在导航栏中,有一个按钮用于启动模式。显示时,父控制器对每个子视图多次调用
setNeedsLayout
。在我的演示项目中,我正在覆盖
setNeedsLayout
以在访问它时记录它。关闭模式时也会发生同样的情况。打开和关闭模态开关几次,观察控制台

我看不出为什么需要一个新的布局,对于更复杂的视图,我发现有数百个这样的调用正在启动,对性能有着显著的影响

请注意,如果省略了
ChildView
中的布局代码,则不会调用
setNeedsLayout
。我鼓励您对约束进行注释,并查看日志记录中的差异


为什么会这样?如何防止在显示和取消模式时出现不必要的布局过程?

首先,您正在记录
setNeedsLayout
,这只是一种标记机制,实际上还没有引起任何工作。对
setNeedsLayout
的多次调用可能只触发一个布局。您应该改为记录
-[UIView layoutSubviews]
-[UIViewController viewDidLayoutSubviews]
,因为这些是实际的繁重工作发生的地方

第二,在演示过程中,与布局相关的方法需要反复快速调用,因为:

  • 窗口需要旋转其所有子视图,以符合显示的视图控制器的首选界面方向
  • 动画需要知道视图的初始和最终状态
  • 无论出于何种原因,当父视图上出现布局时,它们的所有子视图(可能包括视图控制器的视图)当然也需要更新它们的布局

  • 如果要最小化布局过程的数量,可以尝试放弃使用
    presentViewController:animated:
    ,而是使用
    addChildViewController:
    手动设置必要视图的动画。但即使如此,您仍然可以触发父控制器的布局。

    首先,您正在记录
    setNeedsLayout
    ,这只是一种标记机制,实际上还没有引起任何工作。对
    setNeedsLayout
    的多次调用可能只触发一个布局。您应该改为记录
    -[UIView layoutSubviews]
    -[UIViewController viewDidLayoutSubviews]
    ,因为这些是实际的繁重工作发生的地方

    第二,在演示过程中,与布局相关的方法需要反复快速调用,因为:

  • 窗口需要旋转其所有子视图,以符合显示的视图控制器的首选界面方向
  • 动画需要知道视图的初始和最终状态
  • 无论出于何种原因,当父视图上出现布局时,它们的所有子视图(可能包括视图控制器的视图)当然也需要更新它们的布局

  • 如果要最小化布局过程的数量,可以尝试放弃使用
    presentViewController:animated:
    ,而是使用
    addChildViewController:
    手动设置必要视图的动画。但即使如此,您仍然可能会触发父控制器的布局。

    您正在做一件非常非常奇怪的事情:您正在维护一个自定义父视图控制器,其中包含10个子视图控制器,所有子视图控制器的视图都同时在接口中。视图控制器不是为这类事情而设计的。正是它触发了您看到的多个
    layoutSubviews
    调用。可以有多个子视图控制器,但它们的视图不应该都在层次结构中,特别是在您的情况下,只有一个这样的子视图是实际可见的

    事实上,您构建的界面——一个分页滚动视图,其每个“页面”都是由视图控制器管理的视图——已经由UIPageViewController为您实现,这要高效得多,因为它实际上一次最多只维护三个视图控制器:视图控制器管理滚动视图中的可见视图,视图控制器管理其右侧和左侧的视图。它也非常方便和容易使用

    因此,要么:

    • 您应该使用UIPageViewController,或者

    • 您应该模仿UIPageViewController所做的,当视图控制器的视图滚动到看不见的地方时,删除视图控制器的视图(甚至可能释放视图控制器),就像我们在UIPageViewController出现之前所做的那样,请参阅WWDC 2011中的高级滚动视图技术视频。在UIPageViewController出现之前,我的拉丁语“flashcard”应用程序就是这样工作的;它有数千个词汇卡,每个词汇卡由一个视图控制器管理,但在任何时刻最多只存在三个卡片视图控制器

    (顺便说一句,你也不应该使用你自己的
    self.childControl