Ios activateConstraints:和deactivateConstraints:在IB中创建的约束旋转后不保持
新的Ios activateConstraints:和deactivateConstraints:在IB中创建的约束旋转后不保持,ios,cocoa-touch,autolayout,nslayoutconstraint,Ios,Cocoa Touch,Autolayout,Nslayoutconstraint,新的NSLayoutConstraint方法activateConstraints:和deactivateConstraints:似乎不能正确使用IB创建的约束(它们确实可以正确使用代码创建的约束)。我创建了一个简单的测试应用程序,其中一个按钮有两组约束。一组已安装,具有centerX和centerY约束,另一组已卸载,具有顶部和左侧约束(常数10)。按钮方法切换这些约束集。这是密码 @interface ViewController () @property (strong, nonatomi
NSLayoutConstraint
方法activateConstraints:
和deactivateConstraints:
似乎不能正确使用IB创建的约束(它们确实可以正确使用代码创建的约束)。我创建了一个简单的测试应用程序,其中一个按钮有两组约束。一组已安装,具有centerX和centerY约束,另一组已卸载,具有顶部和左侧约束(常数10)。按钮方法切换这些约束集。这是密码
@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");
}
当应用程序启动时,按钮位于安装的约束定义的正确居中位置。在我使用按钮的操作方法激活/禁用按钮后,按钮将正确地移动到其新位置,但当我将视图旋转到横向时,它将移回其最初定义的位置(尽管日志仍显示新激活的集处于活动状态)。当我旋转回纵向时,按钮保持在其初始位置(在屏幕中居中),现在日志显示初始约束集为活动约束,而我激活的约束集为非活动约束
问题是,这是一个bug,还是这些方法不应该在IB定义的约束下以这种方式工作?问题是,您正在做一些与故事板中的“卸载”约束不一致的事情。他们在那里,但不在那里。“卸载”约束仅用于大小类!如果要让Xcode在旋转时自动为您交换约束,可以使用它们。Xcode无法处理您正在做的事情。但是,如果在代码中创建第二组约束,一切都会正常工作 所以,做这个。删除两个“卸载”约束,并删除
uninstalledConstraints
outlet。现在用以下代码替换整个视图控制器代码:
@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;
}
现在反复按下按钮。如你所见,它在两个位置之间跳跃。现在旋转应用程序;按钮保持在原来的位置。我遇到了类似的情况 我在interface builder中创建了两组NSLayoutConstraints。每套一箱。一套已“安装”,另一套未安装 当我切换案例时,布局约束的共同响应集被激活,另一个被取消激活。如Qusteion中所述,前后旋转不能正常工作 通过在interface builder中安装这两个集合来解决此问题。为了消除警告,我对第二组使用了低优先级(999)。 这对我有用 顺便说一句:Strang我在另一个viewcontroller上使用了“已安装/未安装”的方法,他们的方法有效 在不工作的情况下,viewcontroller被嵌入到containerview中,也许这就是原因 您可以使用此工作流,尽管这显然不是当前苹果员工支持的用例 诀窍是不要卸载约束(正如@matt也指出的),而是在布局发生之前在
UIViewController
子类的viewDidLoad()
中停用约束(冲突的约束会导致问题)
我现在用的是那种方法,效果很好。当然,在理想情况下,我们可以通过激活和禁用约束(中间有免费动画),直观地创建约束组并像关键帧一样使用它们:)oooh,很好,现在我们开始着手解决问题。你能在github上发布这个项目吗?我一直在期待这一点。@matt,这是链接,对吧,但这不是因为你在故事板中卸载约束并向它们提供一个出口是不连贯的吗?我希望你能按照我的要求将它放在github中,因为那样我就可以向你推送我的修复了。相反,我必须用文字来描述它。我对“卸载”有同样的误解,基本上也有同样的问题,但我花了很长时间寻找这个问题及其解决方案。因此,我编辑了标题以帮助页面的搜索能力。对不起,我错过了Github部分。你真的不需要发布任何代码,一句话,“卸载”约束只适用于大小类!“那就足够了。很高兴知道记录在哪里。我花了几个小时观看WWDC视频,试图找到有关activateConstraints/deactivateConstraints的任何信息。关于它们的文档很薄。问题是,它们完全是正交的。activate/deactivate与卸载的内容无关。”约束问题。如果您使用了
removeConstraints
和addConstraints
,这将是一个同样混乱的问题。正是卸载的约束及其出口扼杀了一切。对多个大小类使用已安装/卸载的约束有很好的文档记录;这就是它们的用途r、 我知道,令人失望的是,您不能在故事板中同时绘制这两组约束,但事实就是如此。我已经看到了使用大小类安装和卸载约束的文档,但我似乎遗漏了对约束的“安装”或“卸载”含义的任何基本解释。因此,我的(错误)了解到,卸载的约束相当于在代码中创建约束,但没有将其添加到视图中。你能告诉我这个概念在哪里得到了很好的证明吗?有一个关于编写自适应应用程序的WWDC视频,讨论了“已安装”的内容“复选框用于。-我重复一遍,您希望在Interface Builder中设计这两组约束的愿望并不是非理性的。相反,您有一个简单且有说服力的用例。您应该将其作为增强请求提交给苹果。但现在,您遇到了一个edge案例,应该避免它(正如您自己的结果所示)@matt你在自我之间有一个空间