19

I have an app that was built using auto-layout and everything still works as expected when I run it on my iOS 7 device, however when I run it on an iOS 8 device some of my constraints go a little wacky.

I actually experienced a similar issue in another app but it wasn't a big issue. Now, I'm starting to wonder if it is a bug in the iOS 8 SDK or if there is a new way of handling auto layout in iOS8 that I'm not aware of.

Here is my setup: I have a UIView with a UIImageView embedded inside it. Both the view and the image view have constraints pinning their bottom, leading & trailing edges to their superviews with constant = 0.

The UIView also has its top edge pinned to its superview and I have an IBOutlet connected to the constraint in order to adjust it programatically. The UIImageView has a fourth constraint fixing its height to the height of the device (in my case 568).

Here is the behavior I am expecting/achieving in iOS 7: I am trying to shrink the height of the container view and cause the top of the image view to be cut off w/o the aspect ratio changing (sort of looks like you cropped the top of the image off)...this is why I have pinned the height of the image view and the bottom edge.

What actually happens in iOS8: The container view shrinks as expected (it stays pinned to the sides & bottom & the height shrinks). The UIImageView behaves as if it had a top space constraint with cosntant == 0. Instead of cutting off the top of the image, the whole image shrinks down. Since I have the image in AspectFit mode, the sides pinch in as well to keep the aspect ratio the same (but the imageView itself remains pinned to the leading, trailing & bottom edges as it should).

How I do it: I have a notification that fires from another part of my code to adjust the top-space constraint hooked up to the IBOutlet. The method it calls is really quite simple:

- (void) setTopSpaceForContainerView:(NSNotification*) notif{
    containerView_TopSpace.constant = [[notif.userInfo objectForKey:kTopSpace] intValue];
    [self.view setNeedsUpdateConstraints];
    [self.view setNeedsLayout];
}

Anyone else have a similar experience? I'm trying to find a workaround, but iOS 8 just seems determined to shrink my image.

Thanks a ton!

Meet Doshi
  • 4,241
  • 10
  • 40
  • 81
BFar
  • 2,447
  • 22
  • 23
  • 2
    I'm having problems which may be related: http://stackoverflow.com/questions/25987244/autolayout-problems-with-ios8-with-code-that-works-fine-on-ios7 My app was fine on iOS7 and messed up on iOS8. I'm still digging on this one but no daylight yet. – Gallymon Sep 23 '14 at 17:13
  • 1
    Same boat here with scrollview : http://stackoverflow.com/questions/26047595/extra-top-white-space-since-ios-8-using-autolayout-and-scrollview No answer yet – Pilouk Sep 26 '14 at 00:16

2 Answers2

10

This is definitely an iOS 8 bug. I was able to work around it by sending setNeedsLayout to the container view (the superview of the image view).

I see that you're sending setNeedsLayout to self.view. If that code is in your view controller, then I guess self.view is not the container view. Try sending setNeedsLayout to the container view directly.

Demo project is here.

enter image description here

rob mayoff
  • 375,296
  • 67
  • 796
  • 848
  • It works! +1 more because this is backwards compatible for iOS 7 as well. Which makes me wonder, in iOS7 calling `setNeedsUpdateConstraints` and `setNeedsLayout` on the root view automatically trickled down to all the subviews. Now we need to call setNeedsLayout specifically on the views that have constraints changing...that seems like it could reduce unnecessary layout calculations and speed things up. Should I have been doing it this way all along? – BFar Sep 26 '14 at 23:41
  • I don't think it trickled down in the way you think. I think that in iOS 7, changing the constraint constant flagged the constrained views as needing layout (or triggered the constraint solver in some other way), and in iOS 8 it doesn't. – rob mayoff Sep 26 '14 at 23:54
  • Yes, that makes a lot of sense. Sounds like it is time for many of us to go fix all of our `setNeedsLayout` calls to point to the views that have a changing constraint. – BFar Sep 27 '14 at 00:00
  • I'm really excited to try this on my problem and see if things sort out: http://stackoverflow.com/questions/25987244/autolayout-problems-with-ios8-with-code-that-works-fine-on-ios7 If so, I'll be back to mark this puppie UP! – Gallymon Sep 27 '14 at 04:45
  • I've been thinking more about this. In iOS6/7, I've had two levels of nested VC's and I've never called setNeedsUpdateConstraints nor setNeedsLayout. The layouts have always, up until iOS8, just seemed to lay themselves out. The only thing I've done was to wait for viewDidLayoutSubviews so I could do something that I couldn't do until I knew all the calculations were over. So, is the difference that now we have to explicitly ask for updates? Still a bit puzzled about all of this. – Gallymon Sep 27 '14 at 07:49
  • I believe it's a bug that iOS 8 doesn't run auto layout when you change a constraint constant. – rob mayoff Sep 27 '14 at 13:38
  • @robmayoff Can you please put together a simple sample project that demonstrates this issue (e.g. works on 7 SDK, but not on 8 SDK) and then file a radar and share the radar #? As you suggest this seems to be a bug: https://twitter.com/mairwatching/status/516985359414992897 – smileyborg Sep 30 '14 at 16:24
  • @smileyborg [Project is here.](https://github.com/mayoff/ios-8-layout-bug) You file the radar. – rob mayoff Sep 30 '14 at 17:01
  • @robmayoff Haha, sure. Thanks for the project, let me check it out and file. – smileyborg Sep 30 '14 at 17:02
  • Filed as rdar://18502293 – smileyborg Sep 30 '14 at 17:56
  • Bravo for doing the radar, friends. robmayoff, ultimately, your issue and mine do not seem to be related. But, Ive got legal workarounds that are allowing me to go forward now. Cheers, – Gallymon Oct 03 '14 at 01:57
  • 4
    The radar has been picked up by Apple and fixed. It is an iOS 8 bug. See https://twitter.com/mairwatching/status/517747734564990976 Here are more details: https://twitter.com/mairwatching/status/517748417452208129 – smileyborg Oct 03 '14 at 17:22
-1

Try using UIViewContentModeScaleAspectFill and setClipsToBounds:NO

David Pettigrew
  • 299
  • 2
  • 10