Whilst developing an iPhone app, I have come some very odd behaviour in UIScrollView. Ok, I’ll admit what I was doing was somewhat unusual, but I think the issue could occur in less unusual circumstances.
The effect appeared to be that the UIScrollView was remembering the last user scroll page position, despite my changing the frame, contentSize and contentOffset of the view manually. If the user touched the scroll view after my programmatic changes, the view would immediately scroll back to the page that had last been user scrolled to.
Consider the following situation: we start with the scrollview (and content) looking like
[1 2 3 4] 5 6 7 8
where the brackets denote the visible page area. I manually scroll to show the second page:
1 2 3 4 [5 6 7 8]
which works fine. I then change to “selected” mode programmatically, and the display now shows:
1 2 3 4 5 6 [7] 8
again, which works fine.
However, if I now tap on the UIScrollView it immediately scrolls to
1 2 3 4 [5] 6 7 8
for no apparent reason.
This was going to be a complete show stopper for me, so I spent quite a long time delving into the mysteries of UIScrollView, and to cut a long story short, I think I’ve found a bug. I’ve opened a bug report with and submitted a test case, but not heard anything yet, so I’ll update this post as and when they confirm or refute it.
However, the good news is that while investigating what was causing the problem, having guessed at the cause, which I think is a rounding error between two different member variables, responsible for handling the paging enabled mode, a workaround idea presented itself.
What I discovered was, that if the content view width was integer divisible by the number of pages (which in this case was 2 or 8 pages wide), the problem didn’t happen, whereas if the content size divided by the number of pages resulted in a fraction, the issue occurred. Thankfully, this was a fairly easy workaround to implement, and perhaps explains why it hasn’t shown up often enough for apple to have found it previously.