启动Xcode,为了清楚起见,仅用9.3版通用应用程序进行构建。因此,将9.3 iPad与9.3 iPhone进行比较。构建模拟器和设备-在这两者上发行展览。
该应用程序沿所有四个方向旋转。
在典型情况下,您会执行以下操作...

@IBOutlet weak var doorHeightPerScreen: NSLayoutConstraint!

var heightFraction:CGFloat = 0.6
    {
    didSet
        {
        if ( heightFraction > maxHeight ) { heightFraction = maxHeight }
        if ( heightFraction < minHeight ) { heightFraction = minHeight }

        let h = view.bounds.size.height
        spaceshipHeightPerScreen.constant = h * heightFraction

        self.view.layoutIfNeeded()  // holy!  read on....
        }
    }
注意更改约束后的layoutIfNeeded()
继续典型的例子,您将得到类似
override func viewDidLayoutSubviews()
    {
    super.viewDidLayoutSubviews()
    heightFraction = (heightFraction)
    // use "autolayout power" for perfection every pass.

    // now that basic height/position is set,
    save/load reactive positions...
    position detail stuff...
    }
看看...我整天都在这样做,只是碰巧使用iPhone。
有趣的是,您不需要调用layoutIfNeeded。
@IBOutlet weak var doorHeightPerScreen: NSLayoutConstraint!
var heightFraction:CGFloat = 0.6
    {
    didSet
        {
        if ( heightFraction > maxHeight ) { heightFraction = maxHeight }
        if ( heightFraction < minHeight ) { heightFraction = minHeight }
        let h = view.bounds.size.height
        spaceshipHeightPerScreen.constant = h * heightFraction
        }
    }
工作良好。
但是,最终,我把它放在一些iPad上,..一切都破了!
每当您旋转风景/肖像时,都会出现问题。
经过一番摸索,我意识到您确实需要iPad上的layoutIfNeeded调用 。在相同的操作系统上。
确实,无论操作系统版本如何,行为都会表现出来。并且它适用于所有iPhone /所有iPad。 WTF!
@IBOutlet weak var doorHeightPerScreen: NSLayoutConstraint!
var heightFraction:CGFloat = 0.6
    {
    didSet
        {
        if ( heightFraction > maxHeight ) { heightFraction = maxHeight }
        if ( heightFraction < minHeight ) { heightFraction = minHeight }
        let h = view.bounds.size.height
        spaceshipHeightPerScreen.constant = h * heightFraction
        self.view.layoutIfNeeded() //MUST HAVE, IN IPAD CASE!!!!!!
        }
    }
对我来说,令人难以置信地困扰,它们的工作原理有所不同。
我想知道的是,也许有某个设置可以使它们相同地工作?莫非是我的错?
两者之间是否还有其他已知的区别-还是确实“知道”有一些这样的错误?
我想不出我在任何地方都做过什么奇怪或不寻常的事情,除非整个应用程序在第一个视图中都有override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask { return .All },这是正常的,如果您想将设备倒置的话。我怀疑它的相关性。除此之外,它是一个非常“干净”的新鲜应用程序。
它给了我矩阵故障的感觉-这太可怕了。
是什么原因造成的?

按照RobM的问题,初始ViewController上的SimulatedMetrics设置(“属性”选项卡)为...
ios - 令人恐惧的是,layoutIfNeeded序列在iPad和iPhone上的行为有所不同。怎么修?-LMLPHP

该应用的总体方案:第一个场景“常规”为全屏,即设备的大小。有一个“Live”容器,它的大小相同(使用“Trailing”等/约束为零)。在Live中,有一个容器视图“Quad”,实际上它的大小也已完全调整为“Live”,因此它也是全屏的。 Quad:UIViewController展示了我描述的问题。 Quad包含位于视图周围的各种对象(图像,自定义控件等)。应用启动时,一切正常。
在设备(或类似设备)旋转时:更改约束之后(我不知道这是否相关):iPad(所有iPad)需要layoutIfNeeded调用,而iPhone(所有iPhone)则不需要。在模拟器和设备上,行为是相同的。

另一个例子 .....
我发现了另一个令人震惊的例子。
在UICollectionView中,自定义单元格(只是简单的静态大小的单元格)。如果您碰巧要更改约束(例如说调整单元格中图标或产品拍摄的大小)。
在IPAD上,您必须确保重新调整layoutIfNeeded,否则它将在单元格的首次出现时不起作用。
在IPHONE上上的行为肯定不同:如果在单元格初次出现之前,它将“为您做到这一点”。
完全怪异!
我在每个iPad和每个iPhone上都进行了测试。 (此外,异常行为正好表现在设备或模拟器上:模拟器没有区别。)

最佳答案

我无法复制您所看到的内容;很高兴看到一个完整的例子。在我的模型中,我为视图控制器配置了一个视图,该视图具有一个子视图,并带有控制子视图高度的约束。我根据视图大小在viewDidLayout中更改了子视图高度约束。 iPhone和iPad的行为均相同,并且在任何视图上都可以调用layoutIfNeeded来工作。

就是说,我认为一旦视图完成布局,您就在更改子视图约束-是吗?我认为更好的方法是通过 viewWillTransitionToSize:withTransitionCoordinator: 在子视图之前进行布局。

func viewWillTransitionToSize(_ size: CGSize,
    withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator)

这样,视图层次结构的自动布局可以一次完成。仅在视图更改大小时才调用此方法,因此在第一次加载视图时将不会调用此方法。您必须在其他地方设置初始约束-因为它们取决于视图大小,也许您可​​以使用viewWillAppear

或者(可能更正确),将视图控制器的视图子类化,并覆盖updateConstraints。这是更改约束常量的最合适的位置。

最后,在属性设置器中,永远不要调用view.layoutIfNeeded()。如果有的话,可以设置view.setNeedsLayout(),以便在下一个运行循环迭代中进行布局,并拾取可能需要表示的所有更改。

关于ios - 令人恐惧的是,layoutIfNeeded序列在iPad和iPhone上的行为有所不同。怎么修?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/37624943/

10-12 14:30
查看更多