碾碎的布局

我有以下人造视图控制器:

@interface ViewController () @property (nonatomic, strong) IBOutlet UILabel *l1; @property (nonatomic, strong) IBOutlet UILabel *l2; @property (nonatomic, strong) IBOutlet UITextField *input1; @property (nonatomic, strong) IBOutlet UITextField *input2; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; [self.view removeConstraints:self.view.constraints]; for (UIView *view in @[self.l1, self.l2, self.input1, self.input2]) [view setTranslatesAutoresizingMaskIntoConstraints:NO]; NSDictionary *views = @{ @"l1" : self.l1, @"l2" : self.l2, @"input1": self.input1, @"input2" : self.input2, @"topLayout" : self.topLayoutGuide}; NSArray *constraints; constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[l1]-[input1]" options:NSLayoutFormatAlignAllCenterY metrics:nil views:views]; [self.view addConstraints:constraints]; constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[l2]-[input2]" options:NSLayoutFormatAlignAllCenterY metrics:nil views:views]; [self.view addConstraints:constraints]; NSString *v1 = @"V:|-20-[input1]-[input2]"; constraints = [NSLayoutConstraint constraintsWithVisualFormat:v1 options:0 metrics:nil views:views]; [self.view addConstraints:constraints]; NSString *v2 = @"V:|-20-[l1]-[l2]"; constraints = [NSLayoutConstraint constraintsWithVisualFormat:v2 options:0 metrics:nil views:views]; [self.view addConstraints:constraints]; } @end 

结果如下:

在这里输入图像说明

如果我只是简单地改变v1和v2来使用topLayoutGuide:

 NSString *v1 = @"V:[topLayout]-20-[input1]-[input2]"; NSString *v2 = @"V:[topLayout]-20-[l1]-[l2]"; 

屏幕看起来像这样所有scrunched:

在这里输入图像说明

我可以得到这个消失,当我停止使用NSLayoutFormatAlignAllCenterY水平约束,但是我的行不再排队适当:

在这里输入图像说明

为什么会出现这个问题,在使用topLayoutGuide的时候,怎样才能正确排列行?

简而言之,这个问题是,你不了解由storyboard / nib通过自动布局产生的约束和你的代码产生的约束之间的关系。 因此,你的约束总是不好的(即使视觉布局看起来是正确的)。 顶层布局指南的问题只会使您的约束条件变得更加明显。

但是,我宁愿不要说这个点(即所有的代码是做错的东西); 我宁愿直接跳到正确的方法。 准备? 只需执行以下操作:

  1. 在你的代码中,删除这一行(这实际上是90%的麻烦的原因):

     [self.view removeConstraints:self.view.constraints]; 
  2. 在故事板中:

    一个。 给所有四个元素(两个标签和两个文本字段) 每个左(前导)约束和顶部约束。

    湾 select您刚刚完成的所有八个约束,并在“属性”检查器中选中“在构build时删除”的checkbox。

现在你的代码将完全按照你的意愿工作。

正如我所说的,我不想详细说明这是为什么,但基本上我已经指示你做的是在自动布局下在storyboard / nib中创build视图的正确方法,但只适用于那些视图在代码中生成。


请注意,你也可以删除这一行:

 for (UIView *view in @[self.l1, self.l2, self.input1, self.input2]) [view setTranslatesAutoresizingMaskIntoConstraints:NO]; 

它没有什么坏处,但它也没有什么好处,因为这些视图已经不能将它们的自动修复面具转化为约束。


最后一点:我们刚才所做的一切都是非常愚蠢的,因为你可以采取两种更常用的方法之一:

  • 我们可以在故事板/笔尖中生成所有这些约束并简单地删除所有的代码。

  • 或者,恰恰相反,我们可以从故事板/笔尖删除子视图,并在代码中创build子视图(并将它们添加到代码中的self.view中)。

这两者中的任何一个都意味着你的代码可以正常工作(除了关于删除所有约束的部分,这总是一个灾难性的想法)。 但是,我告诉你如何去做你正在做的事情,只是为了配合这个假设。