20

I am trying to make very simple element with new iOS 6 SDK with auto layout. I have an ImageView and Embed it in ScrollView. (everything build with Interface Builder). The .png file is set and imageView mode is set to "Top Left".

Implementation:

#import "ImaginariumViewController.h"

@interface ImaginariumViewController ()
@property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@end

@implementation ImaginariumViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.scrollView.contentSize = self.imageView.image.size;
    self.imageView.frame =
    CGRectMake(0, 0, self.imageView.image.size.width, self.imageView.image.size.height);
}

@end

When I run the app, the image is not scrolled. Doing all the same with auto layout turned off (with struts and springs), I have working scrolling. I guess the problem is with constraints. Could anybody help me, please?

Vitaly
  • 501
  • 1
  • 5
  • 17

2 Answers2

52

I just encountered the same issue in a tutorial that I was updating. I attempted programmatically deleting constraints, cursing, and banging my head against the wall - no luck.

About 5 minutes ago, however, I tried something that had fixed another issue I encountered, and, ta da! UIScrollView is working again! The solution was to move the old code that sets the UIScrollView contentSize property into an implementation of viewDidAppear, rather than viewDidLoad:

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    self.theScroller.contentSize=CGSizeMake(200.0,2000.0);
}

I hope this helps someone else encountering some of the headaches that have appeared with Auto Layout.

John E. Ray
  • 636
  • 6
  • 4
  • This works, thank you! Really strange Apple haven't put info on this in iOS 6 docs. Probably the problem is because constraints are set later than -viewDidLoad is called (tho as it comes from storyboard it should be set on awakeFeomNib, earlier than viewDidLoad called, as fas as I know). – Vitaly Sep 30 '12 at 12:41
  • 2
    Though there's another problem with zooming of the imageView inside the scrollView. – Vitaly Sep 30 '12 at 16:14
  • MY GOD that was so annoying. So much time wasted! As soon as it was moved to viewDidAppear from viewDidLoad it worked fine. Thanks John! – Andy Davies Oct 11 '12 at 13:14
  • This works as intended. But I wonder if there's a way to set the contentSize of a UIScrollView (with autoLayout enabled) before changing it in viewDidAppear. I couldn't get this working when I removed the code out of the viewDidAppear method... – Yannick Nov 09 '12 at 21:10
  • Worked like a charm dammit, i wasted 2 days on this issue – Muhammad Umar Dec 22 '12 at 16:16
  • Did you happen to try putting it in `- (void)updateViewConstraints`? That seems like it may provide a way to handle if the contentSize changes after the view is loaded. – Tim Shadel Jan 24 '13 at 03:38
  • 2 hours after trying every weird combination of auto resizing masks and whatnot possible, this is the solution. *ugh* – mszaro Sep 05 '13 at 19:29
27

Autolayout can be very confusing at first. You actually don't want to set the contentSize of the scrollview anywhere. With a pure autolayout approach the scrollview sets its own content size. See the section on autolayout and UIScrollView in the iOS 6 release notes:

The constraints on the subviews of the scroll view must result in a size to fill, which is then interpreted as the content size of the scroll view. (This should not be confused with the intrinsicContentSize method used for Auto Layout.)

Note that this means that the constraints on the subviews of the scrollview must set explicit widths and heights and not use widths that vary based on aspects of the scrollview.

The second error here is that you set the frame of the UIImageView to the size of the image. With autolayout this is also unnecessary. The UIImageView actually has an intrinsicContentSize which is the size of the underlying image. (To change this you should set constraints for width and height with a high priority) That means that with auto layout to place an image in a scrollview and have it scroll the correct code should be the following:

** nothing at all!!! **

But theres still something you need to watch out for that could cause you to have an image that appears not to scroll and the hint is in the aforelinked release notes:

Note that you can make a subview of the scroll view appear to float (not scroll) over the other scrolling content by creating constraints between the view and a view outside the scroll view’s subtree, such as the scroll view’s superview.

i.e. if you set constraints in interface builder and constrain the image view to a view above the scrollview in the hierarchy it will affect how the view appears to scroll. Mad!

Happy Coding...

jackslash
  • 8,550
  • 45
  • 56
  • Thanks. Your notes about setting the image view to have a high priority width/height helped me – bean Nov 28 '12 at 10:26
  • Hey @jackslash was wondering if you know how to create a constraint between the view and the scroll view's superview (as an example). I've been trying for a while now and can't see how to do it. – Ants Feb 15 '13 at 04:57
  • @Ants That sounds like a whole new question to me! If you make one link it here so i see it. – jackslash Feb 15 '13 at 11:13
  • Here's my question (http://stackoverflow.com/questions/14927532/how-to-make-a-view-float-over-a-scroll-view-using-autolayout/14927581#14927581). I answered it with something I got going today. – Ants Feb 18 '13 at 00:02
  • 2
    This should be the accepted answer. John's answer is mostly a hack, and could break your constraints. – Guillaume Algis Mar 11 '13 at 17:41
  • 1
    I found the following tutorial helpful: http://stackoverflow.com/questions/19112189/how-to-make-a-scrollview-with-autolayout-in-xcode5/19112639#19112639 The approach is similar (or the same) with jackslash's. – MiuMiu Oct 07 '13 at 03:30