Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Event tracking in UIScrollView blocks the main thread. Any fixes?

Tags:

iphone

Event tracking in UIScrollview blocks the main thread. I'm using the main thread to run a timer that drives some animation -- the result is that any user interaction with the scrollable view (dragging it up or down, etc) causes the animation (running on the main runloop) to freeze. Is there a way around this?

I've tried to RTFM about NSRunloop (CFRunLoopAddCommonMode et al), but it's pretty terse, leading me to believe that tinkering with event priorities / thread priorities is better avoided. Anyone have any insight?

like image 542
Andy Milburn Avatar asked Nov 20 '10 01:11

Andy Milburn


1 Answers

Instead of using one of NSTimer's static constructors, create the timer object and schedule it manually for the "common" run loop modes:

Swift

let timer = Timer.init(timeInterval: 10, repeats: false) { (_) in
    // ... do something useful after 10 seconds ...
}
RunLoop.main.add(timer, forMode: .commonModes)

Objective C

NSTimer *timer = [[NSTimer alloc] initWithFireDate: [NSDate dateWithTimeIntervalSinceNow: delayInSeconds] interval: 0 target:yourObject selector:yourSelector userInfo:nil repeats:NO];
[NSRunLoop.mainRunLoop addTimer: timer forMode: NSRunLoopCommonModes];

Your paramters when constructing the timer will be different since you're using a repeating timer, but the basic idea is to manually schedule the timer for NSRunLoopCommonModes.

What's happening is that when you're scrolling the run loop goes into a mode which prevents "default mode" tasks from executing. The static NSTimer functions all schedule into the default mode which is why they don't fire while you're scrolling. Manually scheduling the timer lets you specify the mode and NSRunLoopCommonModes includes the run mode used by scrolling.

like image 64
John Stephen Avatar answered Sep 21 '22 01:09

John Stephen