对子类 UIView 的约束会抛出以编程方式创建的 UILabel 位置
Posted
技术标签:
【中文标题】对子类 UIView 的约束会抛出以编程方式创建的 UILabel 位置【英文标题】:Constraints on subclassed UIView throw off programmatically created UILabel position 【发布时间】:2014-12-24 16:52:48 【问题描述】:我有一个子类 UIView,它以编程方式创建一个 UILabel,但是当 UIView 被赋予约束时它表现不佳......
我想做什么:
标签应位于视图的顶部。
我的子类 UIView 将创建一个这样的 UILabel:
//In interface
@property(nonatomic, strong) UILabel *myLabel;
//in implementation
self.myLabel = [[UILabel alloc] initWithFrame:[self bounds]];
/*
set properties
*/
[self.superview addSubview:[self myLabel]];
这提供了所需的行为,标签具有与子类 UIView 相同的大小和位置。但是当我在情节提要中向 UIView 添加约束时,UILabel 会呈现在错误的位置。
这是发生了什么:(UIView 阴影为黄色,UILabel 阴影为青色)
我尝试过改变
[self.superview addSubview:[self myLabel]];
到
[self addSubview:[self myLabel]];
但这也不起作用。
如何使 UILabel 呈现在 UIView 之上?
【问题讨论】:
我遇到了类似的问题,不得不转向编程约束而不是基于 IB 的约束来解决它。 您的标签定位是在init
方法中还是layoutSubviews
的覆盖?应该是后者。
目前,我正在从 init 调用 setup 方法。这是我处理标签的地方。如果我把它放在 layoutSubviews 中,似乎每次更新 UIView 时都会创建一个新标签。不确定如何在 init 中添加视图,因此它只添加一个然后在 layoutSubviews 中设置位置,因为标签正在获取 alloc initWithFrame...
【参考方案1】:
如果您在代码中添加标签,您还应该在代码中为其添加约束。 约束的诀窍是记住将约束添加到由约束链接的 2 个视图的(分层)最顶层视图,或添加到第一个公共父视图。
请注意,混合 IB 自动布局和编码约束可能会让人头疼。我遇到过必须将 UIView.translatesAutoResizingMasksIntoConstraints 设置为 NO 才能正常工作的情况。
【讨论】:
从你所说的要清楚,因为这一切都发生在子类 UIView 中,在我的子类 .m 中,我需要将 UIView 或 self 的约束添加到标签或 self。我的标签? 创建约束时,应该是withItem:被约束项toItem:superview。然后将约束添加到超级视图。【参考方案2】:我只是在将 UILabel 添加到 UIView 后尝试了这个:
NSLayoutConstraint *xPosConstraint = [NSLayoutConstraint constraintWithItem:self
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:self.myLabel
attribute:NSLayoutAttributeCenterX
multiplier:1.0
constant:0];
[self addConstraint:xPosConstraint];
导致崩溃的原因...
The view hierarchy is not prepared for the constraint:
<NSLayoutConstraint:0x7fe0f0f750d0 MyUIView:0x7fe0f0f55b90.centerX == UILabel:0x7fe0f0f71810.centerX>
When added to a view, the constraint's items must be descendants of that view
(or the view itself). This will crash if the constraint needs to be resolved before
the view hierarchy is assembled.
Break on -[UIView _viewHierarchyUnpreparedForConstraint:] to debug.
2014-12-24 13:26:40.319 circle[28901:2153934] View hierarchy unprepared for constraint.
Constraint: <NSLayoutConstraint:0x7fe0f0f750d0 MyUIView:0x7fe0f0f55b90.centerX == UILabel:0x7fe0f0f71810'0%'.centerX>
Container hierarchy: < MyUIView: 0x7fe0f0f55b90;
frame = (200 28; 200 200); autoresize = RM+BM;
layer = <CALayer: 0x7fe0f0f54000>>
View not found in container hierarchy: <UILabel: 0x7fe0f0f71810;
frame = (200 28; 200 200); text = '0%'; userInteractionEnabled = NO;
layer = <_UILabelLayer: 0x7fe0f0f71970>>
That view's superview: <UIView: 0x7fe0f0f56760; frame = (0 0; 375 667);
autoresize = W+H; layer = <CALayer: 0x7fe0f0f56a30>>
和
2014-12-24 13:26:40.334 circle[28901:2153934] *** Terminating app due to uncaught exception
'NSGenericException', reason:
'Unable to install constraint on view.
Does the constraint reference something from outside the subtree of the view?
That's illegal.
constraint:<NSLayoutConstraint:0x7fe0f0f750d0
MyUIView:0x7fe0f0f55b90.centerX == UILabel:0x7fe0f0f71810'0%'.centerX>
view:< MyUIView: 0x7fe0f0f55b90;
frame = (200 28; 200 200); autoresize = RM+BM; layer = <CALayer: 0x7fe0f0f54000>>'
另外,像这样将约束添加到超级视图:
[self.superview addConstraint:xPosConstraint];
...导致调试器打破约束,因为它不能被满足。
开始讨厌自动布局...
****编辑**** 修复。嘎。只需要添加这个:
[self.myLabel setTranslatesAutoresizingMaskIntoConstraints:NO];
【讨论】:
以上是关于对子类 UIView 的约束会抛出以编程方式创建的 UILabel 位置的主要内容,如果未能解决你的问题,请参考以下文章