Skip to content

Instantly share code, notes, and snippets.

@k06a
Last active November 28, 2020 04:56
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save k06a/731654e3168277fb1fd0e64abc7d899e to your computer and use it in GitHub Desktop.
Save k06a/731654e3168277fb1fd0e64abc7d899e to your computer and use it in GitHub Desktop.
Executor performing blocks at least after 0.2 sec since last scrolling
static NSTimeInterval const kMinInactiveTime = 0.2;
//
@interface WhenNoScrollingExecutor : NSObject
@property (assign, nonatomic) BOOL runLoopModeWasUITrackingAgain;
- (void)executeBlock:(void (^)())block;
- (void)executeBlock:(void (^)())block completion:(void (^_Nullable)())completion;
@end
@implementation WhenNoScrollingExecutor
- (instancetype)init {
self = [super init];
if (self) {
[self tick];
}
return self;
}
- (void)tick {
if ([[NSRunLoop mainRunLoop] respondsToSelector:@selector(performInModes:block:)]) {
@weakify(self);
[[NSRunLoop mainRunLoop] performInModes:@[ UITrackingRunLoopMode ] block:^{
@strongify(self);
[self tock];
}];
}
else {
[[NSRunLoop mainRunLoop] performSelector:@selector(tock) target:self argument:nil order:0 modes:@[ UITrackingRunLoopMode ]];
}
}
- (void)tock {
self.runLoopModeWasUITrackingAgain = YES;
if ([[NSRunLoop mainRunLoop] respondsToSelector:@selector(performInModes:block:)]) {
@weakify(self);
[[NSRunLoop mainRunLoop] performInModes:@[ NSDefaultRunLoopMode ] block:^{
@strongify(self);
[self tick];
}];
}
else {
[[NSRunLoop mainRunLoop] performSelector:@selector(tick) target:self argument:nil order:0 modes:@[ NSDefaultRunLoopMode ]];
}
}
- (void)executeBlock:(void (^)())block {
[self executeBlock:block completion:nil];
}
- (void)executeBlock:(void (^)())block completion:(void (^_Nullable)())completion {
[self executeBlock:block completion:completion forceWait:NO];
}
- (void)executeBlock:(void (^)())block completion:(void (^_Nullable)())completion forceWait:(BOOL)forceWait {
if (!forceWait && [[NSRunLoop mainRunLoop].currentMode isEqualToString:NSDefaultRunLoopMode]) {
block();
if (completion) {
completion();
}
return;
}
if ([[NSRunLoop mainRunLoop] respondsToSelector:@selector(performInModes:block:)]) {
@weakify(self);
[[NSRunLoop mainRunLoop] performInModes:@[ NSDefaultRunLoopMode ] block:^{
@strongify(self);
[self executeBlockWhenNoScrolling:block];
}];
}
else {
[[NSRunLoop mainRunLoop] performSelector:@selector(executeBlockWhenNoScrolling:) target:self argument:block order:0 modes:@[ NSDefaultRunLoopMode ]]
}
}
- (void)executeBlockWhenNoScrolling:(void (^)())block {
self.runLoopModeWasUITrackingAgain = NO;
@weakify(self);
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(kMinInactiveTime * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
@strongify(self);
[self executeBlock:block forceWait:self.runLoopModeWasUITrackingAgain];
});
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment