Autolayout中的viewDidLayoutSubviews,在UIPageViewController上旋转

时间:2014-03-17 12:47:46

标签: ios objective-c uiscrollview autolayout uipageviewcontroller

我有一个UIPageViewController,其视图控制器包含UIScrollView,其中包含UIImageView。在加载的视图控制器viewWillAppear中,如果旋转视图,则边界不正确。这是我根据this根据图像大小动态定位图像视图的地方。我尝试使用(void)viewDidLayoutSubviews,但我需要调用[self.view layoutSubviews]或者我收到断言错误。当我添加它,然后我不能再缩放图像视图。您可以看到它尝试缩放但调整大小到最小缩放。

我对自动布局完全不熟悉,并试图看看我是否遗漏了一些东西。

我当前的修复涉及检查框架的边界以查看方向是否与边界匹配。如果是这样,那么我按原样使用边界。如果没有,那么我在计算中切换高度和宽度。

我想知道如何正确使用viewDidLayoutSubviews而不会剥夺我放大图片视图的能力。

从两个答案中,看起来viewDidLayoutSubviews可能是布局视图的错误位置。我试图找到应该在哪里完成并让视图知道它们的边界和方向,但在它们在屏幕上可见之前。从我的阅读中,我认为那是viewDidLayoutSubviews,但似乎使用它可能导致无限循环。

3 个答案:

答案 0 :(得分:6)

  

从两个答案中,看起来像viewDidLayoutSubviews可能是   错误的地方布局视图。我试图找到它应该在哪里   完成并让观点了解他们的界限和方向但是   在屏幕上显示之前。

我会继承UIScrollView并覆盖layoutSubviews,只有在需要时以及所有变量(方向,大小等)都具有适当的值时,系统才会为您调用。

答案 1 :(得分:2)

首先,你不应该自己打电话给-layoutSubviews。来自UIView documentation for that method

  

您不应该直接调用此方法。如果你想强迫一个   布局更新,请先调用setNeedsLayout方法   到下一个图纸更新。如果你想更新你的布局   立即查看,调用layoutIfNeeded方法。

即使没有警告,从-viewDidLayoutSubviews调用该方法似乎是一个问题的处方 - 调用-viewDidLayoutSubviews来通知您的视图控制器它的视图只是将其设置为子视图,因此调用{{ 1}}可能很容易导致循环。

  

在加载的视图控制器viewWillAppear中,如果旋转视图,则边界不正确。

请记住,调用[self.view layoutSubviews]时,视图hasn't yet been added to a view hierarchy。鉴于此,您当前的方法似乎并不是一个糟糕的方法。该视图尚未设置其边界(因为它尚未添加),因此您可以确定边界的内容并使用它来设置视图。另一个可能更好的方法是使用-viewWillAppear,因为你的视图将在那时被添加,并且到那时应该有正确的界限。

  

当我添加它时,我无法再缩放图像视图。您可以   看到它试图缩放,但调整大小回到最小变焦。

听起来,当您放置图像视图时,您并未考虑缩放状态。确保-viewDidAppear中的代码不能否定滚动视图正在执行的工作。

你根本不需要改变图像视图的位置 - 这正是自动布局擅长的那种东西。我注意到您作为示例使用的ImageScrollViewController.m文件并未更改图片视图的位置。

答案 2 :(得分:1)

我不完全确定您的视图层次结构,但是如果您有一个包含UIScrollView的视图控制器的视图控制器,此答案将说明如何执行此操作。 (所述视图控制器稍后在UIPageViewController中显示,但这与此无关)。

在视图控制器中覆盖控制滚动视图的以下方法:

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
    [super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];

    CGRect bounds = self.view.bounds;
    self.scrollView.frame = bounds;

    //
    // Calculate a rect for your image view according to bounds
    //
    self.imageView.frame = calculatedFrame;
}

问题是您的视图将在滚动/缩放期间进行布局,如果您将视图放在控制scrollView的视图控制器的viewDidLayoutSubviews中,则每次用户滚动或缩放时都会对其进行定位。

我怀疑你的视图控制器可能直接控制UIScrollView(而不是控制具有UIScrollView子视图的视图),在这种情况下,只需删除self.scrollView.frame = self.bounds行。

您永远不应该从viewDidLayoutSubviews调用[self.view layoutSubviews]。事实上,你根本不应该打电话给那个功能。如果您需要更新布局,请调用[self.view setNeedsLayout]。但是当您的视图执行了其layoutSubviews时,会自动调用viewDidLayoutSubviews。这意味着如果你从那里调用那个函数,你将得到一个无限循环。