activateConstraints:和deactivateConstraints:在IB中创build的约束旋转后不保留

新的NSLayoutConstraint方法activateConstraints:deactivateConstraints:似乎不能正确使用IB创build的约束(它们对代码创build的约束正常工作)。 我创build了一个简单的testing应用程序,其中一个button具有两组约束。 一个已安装的集具有centerX和centerY约束,而另一个已卸载的集具有左上和右约束(常量10)。 button方法切换这些约束集。 这里是代码,

 @interface ViewController () @property (strong, nonatomic) IBOutletCollection(NSLayoutConstraint) NSArray *uninstalledConstraints; @property (strong, nonatomic) IBOutletCollection(NSLayoutConstraint) NSArray *installedConstraints; @end @implementation ViewController - (IBAction)switchconstraints:(UIButton *)sender { [NSLayoutConstraint deactivateConstraints:self.installedConstraints]; [NSLayoutConstraint activateConstraints:self.uninstalledConstraints]; } -(void)viewWillLayoutSubviews { NSLog(@"installed: %@ uninstalled: %@", ((NSLayoutConstraint *)self.installedConstraints[0]).active ? @"Active" : @"Inactive", ((NSLayoutConstraint *)self.uninstalledConstraints[0]).active ? @"Active" : @"Inactive"); } 

当应用程序启动时,button位于由其安装的约束定义的正确的居中位置。 在button的操作方法中激活/closures后,button会正确移动到新的位置,但是当我将视图旋转到横向时,它会移回到其初始定义的位置(尽pipe日志仍然会将新激活的集合显示为活跃)。 当我旋转回肖像时,button保持在其初始位置(居中在屏幕中),现在日志显示约束的初始设置为激活,而激活的约束为非激活。

问题是,这是一个错误,还是这些方法不应该用IB定义的约束以这种方式工作?

问题在于你在故事板上的“卸载”约束条件下做了一些不连贯的事情。 他们在那里,但不在那里。 “卸载”的约束只适用于大小类! 你可以使用它们,如果你打算让Xcode 自动轮换你的交换约束。 Xcode无法应付你在做什么。 但是,如果你在代码中创build第二组约束,一切都会正常工作。

所以,这样做。 删除两个“卸载”约束,并删除uninstalledConstraints出口。 现在用这个replace你的整个视图控制器代码:

 @property (strong, nonatomic) NSMutableArray *c1; @property (strong, nonatomic) NSMutableArray *c2; @property (strong, nonatomic) IBOutletCollection(NSLayoutConstraint) NSArray *installedConstraints; @property (weak,nonatomic) IBOutlet UIButton *button; @end @implementation ViewController { BOOL did; } - (void)viewDidLayoutSubviews { NSLog(@"did"); if (!did) { did = YES; self.c1 = [self.installedConstraints mutableCopy]; self.c2 = [NSMutableArray new]; [self.c2 addObject: [NSLayoutConstraint constraintWithItem:self.button attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTopMargin multiplier:1 constant:30]]; [self.c2 addObject: [NSLayoutConstraint constraintWithItem:self.button attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeadingMargin multiplier:1 constant:30]]; } } - (IBAction)switchconstraints:(UIButton *)sender { [NSLayoutConstraint deactivateConstraints:self.c1]; [NSLayoutConstraint activateConstraints:self.c2]; NSMutableArray* temp = self.c1; self.c1 = self.c2; self.c2 = temp; } 

现在反复按下button。 如你所见,它在两个位置之间跳跃。 现在旋转应用程序; 该button保持在原来的位置。

我面临类似的情况。

我在界面生成器中创build了两套NSLayoutConstraints。 每个设置一个案例。 一套是“安装”,另一套不是。

当我切换的情况下,相应的一组布局约束被激活,另一个被去激活。 正如在Qusteion中旋转和向后旋转中所述,不能正常工作。

通过在接口生成器中安装两套解决此问题。 为了摆脱这个警告,我使用了第二组优先权(999)。 这对我有效。

顺便说一句:Strang我用另一个viewcontroller“安装/未安装”aproach,他们的工作。

在不工作的情况下,viewcontroller被embedded在一个容器视图,也许这是原因。

可以使用这个工作stream程,尽pipe很明显这不是苹果公司目前支持的用例。

诀窍是不要卸载约束(因为@matt也指出),而是在布局发生之前(和你的冲突的约束导致一个问题)在你的UIViewController子类的viewDidLoad()中停用它们。

我现在使用这种方法,它完美的工作。 理想情况下,我们可以直观地创build一组约束,并像关键帧一样使用它们,只需激活和closures它们(在两者之间有免费的animation):)