UITextField中的自动布局:执行-layoutSubviews后仍需要自动布局

7
我正在子类化UITextField,以在左侧添加一个标签。我使用autolayout来布局标签。但是,我一直收到以下崩溃信息:
以下是我的布局代码:
- (void)updateConstraints {

self.segmentLabel.translatesAutoresizingMaskIntoConstraints = NO;

NSLayoutConstraint *constraint;
constraint = [NSLayoutConstraint constraintWithItem:self.segmentLabel attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeHeight multiplier:1.0 constant:0.0f];
[self addConstraint:constraint];
constraint = [NSLayoutConstraint constraintWithItem:self.segmentLabel attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeLeading multiplier:1.0 constant:0.0f];
[self addConstraint:constraint];
constraint = [NSLayoutConstraint constraintWithItem:self.segmentLabel attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeTop multiplier:1.0 constant:0.0f];
[self addConstraint:constraint];
constraint = [NSLayoutConstraint constraintWithItem:self.segmentLabel attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:self.segmentWidth];
[self addConstraint:constraint];

[super updateConstraints];

当我不对文本字段进行任何调整时,这个工作正常。然而,如果我尝试设置占位符文本,我会得到这个异常:
终止应用程序,由于未捕获的异常'NSInternalInconsistencyException',原因是:执行-layoutSubviews后仍需要自动布局。DDSegmentedTextField的-layoutSubviews实现需要调用super。
但是,我没有覆盖-layoutSubviews。有人遇到过这个问题吗?我做错了什么?谢谢!

展示设置占位文本的代码。 - rob mayoff
在控制器的viewDidLoad中,只需将self.tipField.placeholder = @"placeholder"; 添加即可。 - Sean Danzeiser
3个回答

8
所以我几天前也遇到了同样的错误。原来我试图在我的UITextfield子类中布局子视图,设置属性、移动视图等等,但从未明确告诉视图去布局自己(即调用[self layoutIfNeeded])。
iOS 8似乎强制一个视图对其所有子视图进行布局,并配置约束。而iOS 7不会,需要在使用自动布局时显式地告诉视图重绘它们的子视图。
在我的情况下,我已经子类化了UITextField并添加了一个标签到侧边。我通过向UITextfield添加约束来配置标签的框架。我的类上可以调用的公共方法之一是
- (void)setLabelText:(NSString *)newText{
    self.sideLabel.text = newText;
}

当包含我的子类化文本框的视图控制器出现时,这导致我的应用程序崩溃。通过添加 layoutIfNeeded,现在在iOS7和iOS8中一切正常。

- (void)setLabelText:(NSString *)newText{
    self.sideLabel.text = newText;
    [self layoutIfNeeded];
}

每当您更改子类视图的一部分时,都需要调用此函数。这包括添加子视图时进行的设置、更改视图属性等任何事情。在更改视图的函数返回之前,在视图上调用layoutIfNeeded。这似乎适用于一些标准UI控件,包括UITextfield、UITableView和UICollectionView,尽管我确信还有其他控件也适用。希望这足够清晰,并有助于解决您的问题。
您获得的错误并不是非常有用,而且甚至在我的情况下也不适用。尽管我收到了完全相同的错误,但我的所有视图都没有实现layoutSubviews,因此都使用了[super layoutSubviews]方法。

4

这个问题出现在iOS < 8中。

在创建UIView子类和添加视图时,我们可以指示控件首先构造和自动布局子视图。当需要更新UI时,请使用以下语句:

[self layoutIfNeeded];

iOS 8+已经在内部处理了该问题。


-2

我曾经遇到过同样的问题。这可能是由于错误的约束条件引起的,可能是在Storyboard中设置了一些不正确的约束条件。尝试删除其中一些约束条件,看看是否能够找出问题所在。


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