7
votes

I'm subclassing UITextField to add a label on the left side. I'm using autolayout to layout the label. However, I keep getting this crash:

Here's how I am doing my layout code:

- (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];

}

When I don't make any adjustments to the textfield, this works fine.

However, if I try to set the placeholder text, I get this exception:

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Auto Layout still required after executing -layoutSubviews. DDSegmentedTextField's implementation of -layoutSubviews needs to call super.'

However, I'm not overriding -layoutSubviews.

Has anyone encountered this? What am I doing wrong?

Thanks!

3
Show the code that sets the placeholder text.rob mayoff
its just self.tipField.placeholder = @"placeholder"; in the viewDidLoad of the controllerSean Danzeiser

3 Answers

8
votes

So I ran into this same error a few days ago as well. It turns out I was trying to layout subviews inside my UITextfield subclass, setting properties on them, moving them, etc, but was never explicitly telling the view to lay itself out (i.e. calling [self layoutIfNeeded]).

iOS 8 seems to force to a view to layout all its subviews, and then configures constraints on it. iOS 7 won't, and needs you to explicitly tell views to redraw their subviews when you change if you're using autolayout.

In my case, I had subclassed UITextField and added a label to the side. I configured the frame of the label by adding constraints to the UITextfield. One of the public methods I could call on my class was

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

This caused my application to crash when a view controller appeared containing my subclassed textfield. By adding layoutIfNeeded everything now works fine in iOS7 and iOS8.

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

This needs to be called every time you change a part of the view in your subclass. This includes the setup when you add subviews, when you change view properties, anything really. Before the function that's changing your view returns, call layoutIfNeeded on your view. This seems to apply for a few standard UI controls including UITextfield, UITableView and UICollectionView, though I'm sure there are others. I hope this was clear enough and helped solve your problem.

The error you're getting isn't super useful, and didn't even apply in my case. Though I was receiving the exact same error, none of my views implementing layoutSubviews, and thus were all using the [super layoutSubviews] method.

4
votes

This problem shows up in iOS < 8

While creating the UIView subclass and adding views, we can instruct the control to construct and autolayout first the subviews. Use this statement when the UI needs to be updated:

[self layoutIfNeeded];

iOS 8+ are handling the issue quite on there own internally.

-2
votes

I had the same issue. This could be caused by wrong constraints, maybe by some set in Storyboard. Try to remove some of them and see if it works to figure out what's wrong