在Auto Layout约束中更改"installed"的位置在哪里?

12

在故事板中使用自动布局时,有一个“已安装”复选框选项,用于保留或取消保留约束。禁用它将使约束行为就像您没有添加该约束一样 - 它不会产生任何影响。您可以在界面构建器中为不同的大小类配置已安装状态,并且您可以通过将其active属性设置为truefalse来编程更改此值。

在我的应用程序中,我希望仅在设备处于纵向时安装约束-在旋转到横向时应将其“卸载”。这可以通过为iPhone取消勾选任何宽度紧凑高度的已安装来实现。(尽管当旋转到横向时不应该安装它时,似乎不起作用,因为会破坏此约束,但无论如何,UI始终显示为预期的样子。)但是,在界面构建器中,无法卸载iPad在横向上的约束(在两个方向上都是普通宽度普通高度)。

在旋转设备时启用/禁用NSLayoutConstraintactive的正确位置在哪里?更改该状态会以所需的方式产生哪种行为?如果该方法在应用程序启动时未调用,则应将其放置在哪个其他方法中以及旋转方法?

我尝试将以下代码放置在viewDidLoadviewWillTransitionToSize中,但在iPad上运行时会导致一些意外的行为:

  • 在横向启动应用程序会导致约束处于活动状态,尽管已将其设置为false,它会破坏约束,并且UI不会按预期显示
  • 在纵向中启动应用程序会将active设置为true(它已安装在IB中),因此可以按预期工作
  • 在纵向中启动应用程序并旋转到横向会像预期那样工作-约束被设置为非活动状态,它不会破坏约束,UI按预期显示
  • 在纵向中启动应用程序后,将其旋转到横向并返回到纵向会使UI显示正确,但会破坏此已设置为活动状态的约束

如果我在界面构建器中卸载约束,然后运行上述场景,我会获得基本相反的行为。

if size.width > size.height {
    self.myConstraint.active = false
} else {
    self.myConstraint.active = true
}
2个回答

0

我回答有点晚,但是当我面临类似的问题时,解决Autolayout无法检测iOS 7上iPhone的紧凑宽度/紧凑高度的问题,这是我的两分钱。在iOS 7中没有activated属性,所以我不得不添加/删除它们。

我创建了两个方法来添加和删除约束,这些约束已经在IB上设置,并且我使用IBOutlet属性引用它们。因此,由于我要删除它们,与其他IB对象不同,我应该将它们设置为strong,而不是weak。否则,一旦我删除它们,它们就会被销毁,我将无法再次引用它们以重新添加它们。

这是我的约束移除方法:

-(void)removeiOS7andiPhone4inLandscapeToOrientation:(UIInterfaceOrientation)toInterfaceOrientation{

    if( !UIInterfaceOrientationIsLandscape(toInterfaceOrientation )&&(NSFoundationVersionNumber<=NSFoundationVersionNumber_iOS_7_1)&&( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone )){
         // if iPhone with iOS 7 on portrait remove Constraints here

    }
}

这里是约束添加方法:

-(void)addiOS7andiPhone4inLandscapeToOrientation:(UIInterfaceOrientation)toInterfaceOrientation{

    if( UIInterfaceOrientationIsLandscape(toInterfaceOrientation )&&(NSFoundationVersionNumber<=NSFoundationVersionNumber_iOS_7_1)&&( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone )){
       // if iPhone with iOS 7 on landscape add Constraints here

    }

}

关于在何处调用这些方法,就像你尝试的那样,在 viewWillAppear(不需要在viewWillDisappear中调用)和viewWillTransitionToSize 中都要调用它们(在我的情况下,这是willRotateToInterfaceOrientation,因为viewWillTransitionToSize仅适用于iOS 8之后)。按顺序调用它们是有意义的,毕竟只有其中之一会由于使用if来检查它们的横向或纵向方向而运行,在进行必要的更改之前。

以下是我的willRotateToInterfaceOrientation方法定义:

-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{

    [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];

    // this will be run only if orientation is on Portrait
    [self addiOS7andiPhone4inLandscapeToOrientation:toInterfaceOrientation];

    // this will be run only if orientation is on Landscape
    [self removeiOS7andiPhone4inLandscapeToOrientation:toInterfaceOrientation];
}

viewWillAppear中进行类似的调用。

注意:确保在这些方法中进行完全相反的操作,而且你不一定只在addConstraintMethod中添加约束,在removeConstraintMethod中只删除约束。在我的情况下,我在每个方法中都同时添加和删除约束,因此方法的命名并不能完全反映它们的真实作用,但只要你确保进行了完全相反的操作,就可以了。


0
理想情况下,我本来会使用这些方法,但它们的缺点是只有在发生更改时才通知控制器。
/* 
 This method is called when the view controller's view's size is changed by its parent (i.e. for the root view controller when its window rotates or is resized). 

 If you override this method, you should either call super to propagate the change to children or manually forward the change to children.
 */
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id <UIViewControllerTransitionCoordinator>)coordinator NS_AVAILABLE_IOS(8_0);

/* 
 This method is called when the view controller's trait collection is changed by its parent.

 If you override this method, you should either call super to propagate the change to children or manually forward the change to children.
 */
- (void)willTransitionToTraitCollection:(UITraitCollection *)newCollection withTransitionCoordinator:(id <UIViewControllerTransitionCoordinator>)coordinator NS_AVAILABLE_IOS(8_0);

为了在约束方面进行定制,我更倾向于在最初和方向改变时进行。

- (void)updateViewConstraints NS_AVAILABLE_IOS(6_0);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接