66

I have used UIScrollView before, and am using it now, and never had a problem. I'm now adding it to an old app, and while it works as expected (I can look at the contents, scroll around with my finger, all the bounds and sizes are setup right so there is no empty space in the content, etc.), I just can't get scrollToRectVisible to work. I have even simplified the call so that it merely moves to the 0,0 position:

 [scrollView scrollRectToVisible:CGRectMake(0, 0, 10, 10) animated:YES];

or move it to 0,200:

 [scrollView scrollRectToVisible:CGRectMake(0, 200, 10, 10) animated:YES];

I even made a quick app to test this and I can get scrollRectToVisible to work there as I expect. But in my old app, I can't seem to make it do anything.

I can make the scrollView scroll with setContentOffset:, but that's not what I want.

This scrollView and its contents are defined in the nib by IB and used with an IBOutlet. The only code I am using in my app to handle the scrollView is

 [scrollView setContentSize:CGSizeMake(scrollView.contentSize.width, imageView.frame.size.height)];

(I'm only interested in vertical scrolling not horizontal).

Has anyone run into a problem like this?

I have compared the scrollView attributes in both apps and they are identical.

ADDENDUM:

My scrollViews frame is: 0.000000 0.000000 480.000000 179.000000

My scrollViews contentSize is: 0.000000 324.000000

It still acts like the rect I want to scroll to is already visible and no scrolling is needed. Not sure if that is what is happening. This is just the darnest thing. Seems like such an easy thing to resolve...

ADDENDUM #2:

This is how I am making do without scrollRectToVisible:

CGPoint point = myRect.origin;
if (![clefScrollView pointInside:point withEvent:nil]) {
    point.x = 0;
    if (point.y > clefScrollView.contentSize.height - clefScrollView.bounds.size.height)
        point.y = clefScrollView.contentSize.height - clefScrollView.bounds.size.height;
    [clefScrollView setContentOffset:point animated: YES];
}

Everything else about this scrollView works as expected, but scrollRectToVisible. WHY?!? Any wild guesses?

Undo
  • 25,519
  • 37
  • 106
  • 129
mahboudz
  • 39,196
  • 16
  • 97
  • 124

8 Answers8

117

Over a month later, and I finally figured it out. While the alternative above worked well, it has been bugging me and I had to finally figure it out. Turns out that it was somewhat of a stupid mistake.

Here's the old code in my viewDidLoad, where I set up the scrollView:

[clefScrollView setContentSize:CGSizeMake(clefScrollView.contentSize.width, clefView.frame.size.height)];

The value of a scrollView height or width can't be 0! I think this got past me because I was assuming that ScrollView sizes start out with a valid size, and I was missing the fact that one dimension was zero!

This works:

[clefScrollView setContentSize:CGSizeMake(clefView.frame.size.width, clefView.frame.size.height)];
starball
  • 20,030
  • 7
  • 43
  • 238
mahboudz
  • 39,196
  • 16
  • 97
  • 124
  • Thanks! I got bit by this too (I was setting height but not width). – David Dunham Apr 14 '11 at 04:47
  • 3
    This is NOT quite correct - c.f. Orion's answer below (I had a non-zero width/height, it's not '0' that causes the problem...) – Adam Aug 10 '12 at 11:44
  • I have done this in similar way but still scrollRectToVisible is not working. Its working in simulator but not on device. Please help. – Pratik Somaiya Apr 23 '13 at 12:50
  • You want to set 1 instead of 0. Setting height can sometimes hit you in your face, making content size bigger than you actually need (assuming it's not under top/bottom bars). – desudesudesu Mar 17 '14 at 11:29
  • Was driving me crazy! Thanks a ton ;) – sachadso Sep 16 '14 at 10:36
  • THANK You!! My problem was with auto layout - contentSize width was 0. If you have this problem, it's because you didn't put all of your content inside a contentView inside scroll view: http://spin.atomicobject.com/2014/03/05/uiscrollview-autolayout-ios/ If you don't want to do that (which means re-doing all of the constraints), you can add a 0-height view inside your scroll view, set it's leading, trailing, and top edge constraints to that scroll view to 0, add height constraint for 0, and then add equal width constraint between the scroll view and the 0-height view. Yep, weird, but works. – Alex the Ukrainian Oct 08 '14 at 21:41
  • nice detective work, mahboudz. fwiw, i suspect that the problem isn't precisely that the ScrollView can't have a dimension of size zero, but rather that it must be sufficiently large to contain the requested rectangle ! cheers, Orion – orion elenzil Mar 17 '10 at 05:46
  • ALSO: bear in mind that if you set the "zoomScale" this changes the "contentSize" of the scrollview - a little surprising, but that's the way it works. So ... if you zoom out, and try to scale to bottom or right of your "contentSize", it will silently fail because the CURRENT contentSize is now smaller... – Adam Aug 10 '12 at 11:45
51

Yeah, I have not had success with scrollRectToVisible:animated:, but setContentOffset:animated: always works for me. Out of curiosity, why do you not want to use setContentOffset:animated:? It seems to be the proper solution.

Jonathan Sterling
  • 18,320
  • 12
  • 67
  • 79
  • 7
    Unfortunately, setContentOffset will scroll to the point, regardless of whether it is already visible or not. I could do the extra work of determining if the point is visible or not, however, I'm still curious why scrollRectToVisible isn't working, when I see it work in my own sample and other samples on the net. I must be doing something wrong, but with only three or four lines of code for the scrollView, I can't see what?! – mahboudz Oct 02 '09 at 06:11
5

You might want to check and see that the scrollView's delaysContentTouches property is set to NO.

If you call the method scrollRectToVisible or setContentOffset from a touch within a subview of your scrollView then your scrollView could be holding things up by delaying touches.

So, make sure you set the following in your scrollView.

scrollView.delaysContentTouches = NO;

You will most likely be able to move the scrollView with and without animation set to YES.

Michael Colon
  • 151
  • 1
  • 3
1

i had it like this and it didn't work

scrollView.contentSize = CGSizeMake(scrollView.contentSize.width, someKnownValue);

i was just changing the height of the contentSize, so I didn't think that would give me any problem but it did ...

had to change it to this

scrollView.contentSize = CGSizeMake(someOtherKnownValue, someKnownValue);

turns out scrollView.contentSize.width is not necessarily set to a valid value from the get go, so better give it an specific value

Andro Selva
  • 53,910
  • 52
  • 193
  • 240
Rugoso
  • 11
  • 1
0

A little late to the game but I was having the same problem. Though I absolutely had my scrollview's content size set correctly - even excessively so for the height value. Even after extensive checks to validate the frames and content sizes - still wasn't working. I had to adjust the "bounds" frame height, then everything worked great.

user1086279
  • 101
  • 1
  • 4
0

I had the same symptoms as this issue..the scrollRectToVisible was not working as intended. My problem was that the scrollview on the storyboard had a ambiguous constraint problem. Once that was fixed the call worked just fine. It is something else to check when the scrollRectToVisible call isn't working as intended.

Swifty
  • 71
  • 1
  • 1
0

The suggested solution above may still give an error if you haven't set the frame for the "clefScrollView".

If the solution above is used and still having the same problem, make sure you have initialized your scollView (in this case clefScrollView) frame prior to setting the content view.



    clefScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0,0,320,450)];

    [clefScrollView setContentSize:CGSizeMake(clefView.frame.size.width, clefView.frame.size.height)];



aimacworx
  • 539
  • 4
  • 5
0

For me the problem was that a constraint in a subview was not explicit. Check that every constraint in your content is set, even if you are not needing it apparently for the layout.

vicegax
  • 4,709
  • 28
  • 37