Fix for UIScrollView pauses openGL/update?

I know this isn’t a openframeworks specific question, but I wanted to check if anyone had a ‘fix’ for openGL and the whole update function being paused during scrolling a UIScrollView.

I saw this at http://stackoverflow.com/questions/4135-…-cadisplayl and http://stackoverflow.com/questions/4876-…–on-iphone but I’m don’t really understand this in relationship to how oF draws.

In ofxiPhoneAppDelegate.mm there’s a displayLink and like the links above, I changed it from NSDefaultRunLoopMode to NSRunLoopCommonModes, but that didn’t change anything.

Anyone experienced this or have a recommendation?

After further inspection in ofxiPhoneAppDelegate.mm line 120 is commented out

  
// if ([currSysVer compare:reqSysVer options:NSNumericSearch] != NSOrderedAscending) displayLinkSupported = TRUE;  

and therefore “displayLinkSupported” is never true. Thus, the displayLink is never set and therefore can’t be changed to NSRunLoopCommonModes.

After uncommenting the line above and changing to NSRunLoopCommonModes, the displayLink is set to true (3.1 or newer) and then scrolling + opengl/update/timers work at the same time.

I’m not sure what the performance impact is of this though. I’m only using the scrollview in the menu settings so I don’t know if this impacts performance overall or not.

Ok, after more work, it looks like the above isn’t a good ‘fix’.

NSRunLoopCommonModes messes with UIScrollView and basically makes it so scroll views don’t bounce back to position.

The recommendation here: http://stackoverflow.com/questions/4135-…-32#4135232 is to keep using NSDefaultRunLoopMode and call render & present code at -scrollViewDidScroll too, not only in CADisplayLink’s tick callback.

However, I’m not sure where in oF put put -scrollViewDidScroll and how to call the render loop while scrolling.

Any thoughts on this?

I have a habit of answering my own questions…and I couldn’t disappoint again. :wink:

So, for those that want to render/update their OF apps while scrolling, 1) forget everything above and 2) follow below:

In your MyGuiView.h (or whatever your UIViewController is) add a UIScrollViewDelegate so we can listen for scrollView events

  
@interface MyGuiView : UIViewController <UIScrollViewDelegate>{  

and in your MyGuiView.mm implementation add a new function:

  
  
-(void)scrollViewDidScroll:(UIScrollView *)scrollView{  
  
//call the oF timer loop when scrolling since it won't be called otherwise  
[ofxiPhoneGetAppDelegate() timerLoop];  
  
}  
  

Also, in your implementation don’t forget to set your scroll view delegate to ‘self’. If you don’t do this, it won’t work.

  
scrollViewName.delegate = self  

Since scrollViewDidScroll calls it’s method as the scrollView scrolls, we can call the oF timerLoop which calls the oF event system. There’s probably a better way to do this. If anyone has ideas, please let me know. It’d be great to have this setting as part of oF that we can toggle it on/off. I couldn’t figure where to put in as part of oF core though.

The only minor flaw I noticied is if a user holds the scrollView and doesn’t scroll, it won’t call scrollViewDidScroll and therefore update/draw will be paused since the function isn’t called when they’re not actively scrolling.

Nice one, thanks for posting this. ScrollViews did my head in a while back.

No problem David. I hope it helps some others. I doubt i’ll be the only one using a scrollView with oF/openGL especially since it’s so common on iPad (for split views, etc).

Thanks for this post! Did the trick for my app.

In theory, I think it could work to subclass UITableView and implement the touchesBegan:, touchesEnded:, etc. methods, and use them to start and stop an NSTimer that calls the update methods at your specified framerate. I’m not implementing this for now as it’s low on the priority list now that it mostly works.

Hi,

It doesn’t seem to work with OpenFrameworks 0073, does someone has a workaround ? Thanks

OK got it, the trick is the same but write this instead :

  
  
- (void)scrollViewDidScroll:(UIScrollView *)scrollView  
{  
    [[ofxiOSEAGLView getInstance] drawView];  
}  
  

Coming a little late here, but this doesn’t fix it for the use case where the user drags their finger accross the scroll view, then stops. The summary of the solution is you need to start a CADisplayLink when the user begins dragging, and invalidate it when the scroll view stops.

For code:

and background:
https://developer.apple.com/videos/play/wwdc2012/223/