1

I've been using autolayout for a couple of weeks now. Currently, I'm using a 3rd party library called FLKAutoLayout which makes the process easier. I'm at the point where I can construct views the way I want, usually without problem. However, over the past 4 days at work I've been struggling with autolayout once viewcontrollers are involved. I'm fine with all sorts of UIViews... but for some reason, every viewcontroller.view is a total demon. I've had nothing but problems getting a viewcontroller.view to size the way I want and an ever deeper problem is that UIViews of child viewcontrollers do not receive events properly when using autolayout. child viewcontrollers work just fine when designating frames manually, but everything breaks down with autolayout.

I don't understand what's so different about a viewcontroller's UIView that makes it different than all the others... My mind is melting in frustration. Is ios messing with my viewcontroller views behind the scenes or something?

sample image

In the image, the red area belongs to a child view controller. This area should not be going past the bottom most subview (the card that says three). This should be easy and I can get it to work just fine with a bunch of normal UIViews but because this is a viewcontroller, everything breaks...

Can anyone shed light on what it is I don't know. Any leads on potential issues is much appreciated.

Thanks for reading.

Update: The problem may be related to ambiguous constraints

UIView *box = [[UIView alloc]init];
[box addSubview:imageView];
[box addSubview:nameLabel];

imageView constrainWidth:@"32" height:@"32"];
[imageView alignTop:@">=0" leading:@"0" bottom:@"<=0" trailing:@"<=0" toView:box];
[imageView alignCenterYWithView:box predicate:@"0"];

[nameLabel constrainLeadingSpaceToView:imageView predicate:@"5"];
[nameLabel alignTop:@">=0" leading:@">=0" bottom:@"<=0" trailing:@"<=0" toView:box];
[nameLabel alignCenterYWithView:box predicate:@"0"];

[self addSubview:box];
[box alignTop:@"5" leading:@"5" bottom:@"-5" trailing:@"-5" toView:self];

The example above is an ambiguous layout but I can't figure out what's wrong with it...

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
Sethypie
  • 549
  • 6
  • 21
  • You should show the code where you add the child view controller, and what constraints you've tried to add. – rdelmar Jul 10 '13 at 22:52
  • Is any of this in a scroll view? – Maarten Jul 11 '13 at 07:05
  • Nothing is in a scroll view at the moment. However, in the past, when I tried to use a scroll view in autolayout, all the views got squished to be super compact. But, that's another problem for the future. – Sethypie Jul 11 '13 at 17:40

2 Answers2

5

This should probably be a comment, but comments suck for code. ;-)


Did you check for ambiguous constraints? To me this view looks like it could can be caused by ambiguous constraints.

Add this code to your app delegate:

// before @implementation AppDelegate
@interface UIWindow (AutoLayoutDebug)
+ (UIWindow *)keyWindow;
- (NSString *)_autolayoutTrace;
@end

// inside of @implementation

- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event {
    NSString *autolayoutTrace = [[UIWindow keyWindow] _autolayoutTrace];
    if ([autolayoutTrace rangeOfString:@"AMBIGUOUS"].location != NSNotFound) {
        NSLog(@"%@", autolayoutTrace);
    }
    else {
        NSLog(@"No Ambiguous autolayout found");
    }
}

and now shake your simulator. You'll find the shake gesture in the hardware menu.

If it doesn't show "No Ambiguous autolayout found" check for the ambiguous ui element(s) in the trace that was printed. They are marked with "AMBIGUOUS".

Then start to add constraints so there is no more ambiguity.

You can call exerciseAmbiguityInLayout on an UI-Element that has an ambiguous layout to get a hint which constraints are missing.


And make sure to remove the debugging code in your shipping product. You might put those two parts inside of #if DEBUG and #endif

Matthias Bauch
  • 89,811
  • 20
  • 225
  • 247
  • Thanks Matthias! I've found a horde of ambiguous layouts... which kinda sucks but at least I know what to look into now. I'm a little unsure of how to identify which views have ambiguous layouts and what about the constraints is ambiguous. You mentioned using exerciseAmbiguityInLayout but I don't see where that information is displayed... nothing shows up in the debug window anyways. I've used that method on multiple UIViews which have ambiguous constraints but nothing seems to be happening. – Sethypie Jul 10 '13 at 23:32
1

At a certain point in your code you need to add the child view controller to the view controller hierarchy: [topViewController addChildViewController:childViewController];. And don't forget to add -didMoveToParentViewController: afterwards.

This will ensure that your rotation and touch events are forwarded the way you are expecting.

As for your autolayout problems: Erica Sadun has written some very useful autolayout debugging tools. I use it mostly to look at the viewLayoutDescription that she has written in a category on UIView, which prints a very readable lists of the constraints, tells you about ambiguity etc. Give it a try, it really helped me figure out how my constraints were messed up.

Second: always make sure that all of your views have translateAutoresizingMasksIntoConstraints set to NO.

Maarten
  • 1,873
  • 1
  • 13
  • 16