I have a very large horizontally scrolling UIScrollView which is reusing its subviews (moves and updates them when they are out of visible area, similar like UITableView is reusing cells). This relies on scrollViewDidScroll: delegate call, which gives me actual contentOffset, and here I decide when to reuse particular subview. So far so good.
Sometimes I need to change contentOffset programatically, but with custom animation (inertia and bounce back to the final position). I can do this quite easily using core animation.
The problem is, that during custom animation scrollViewDidScroll: delegate method is not called -> I must do it manually so that subviews reusing works. I tried to call it with timer firing each 0.02 sec. Now there are two problems:
I must get UIScrollView contentOffset using [[_scrollView.layer presentationLayer] bounds].origin.x because during animation normal _scrollView.contentOffset does not change.
However info from presentationLayer is not sufficient for exact syncing - sometimes it is bit late.
problem is when the new contentOffset is far from current position. It looks like built-in UIScrollView animation is CAKeyframeAnimation, and scrollViewDidScroll should is called on key frames positions. But I am not able to get these.
If I rely on timer which is not synced with key frames, views are reused on wrong places and I can not see them at all during animation.
Can anyone shed some light on how and when exactly UIScrollView calls scrollViewDidScroll during setContentOffset:X animated:YES? Is it possible to reproduce it without breaking appstore rules?
First of all, I wouldn't use an
NSTimer
with a delay of 0.02 secs - that's not what timers are supposed for. Try using aCADisplayLink
, it fires once per frame.In your callback method you can - if your custom animation is running - run your own physics code and call -setContentOffset:animated: respectively. This even allows you to ease exponentially which CA won't let you.