Skip to content

Instantly share code, notes, and snippets.

@steipete
Last active February 2, 2018 07:32
Show Gist options
  • Star 15 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save steipete/444cb8f3de90d9079bbc to your computer and use it in GitHub Desktop.
Save steipete/444cb8f3de90d9079bbc to your computer and use it in GitHub Desktop.
To work around rdar://19810773, I need a helper that can filter multiple calls to the same method during the same runloop. This is my first attempt on it.
/// Performs `block` immediately and ignores subsequent calls during the same runloop.
#define pspdf_ensureCalledOnlyOncePerRunloop(block) do { \
static const char __onceKey; _pspdf_ensureCalledOnlyOncePerRunloop(self, &__onceKey, block); } while(0)
extern void _pspdf_ensureCalledOnlyOncePerRunloop(id self, const void *key, dispatch_block_t block);
void _pspdf_ensureCalledOnlyOncePerRunloop(id self, const void *key, dispatch_block_t block) {
NSCParameterAssert(block);
NSCParameterAssert(self);
PSPDFAssertOnMainThread(); // run loop needs the main thread.
BOOL hasBeenCalled = [objc_getAssociatedObject(self, key) boolValue];
if (!hasBeenCalled) {
objc_setAssociatedObject(self, key, @YES, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
block();
// clean object in the next runloop
dispatch_async(dispatch_get_main_queue(), ^{
objc_setAssociatedObject(self, key, nil, OBJC_ASSOCIATION_ASSIGN);
});
}
}
// Usage:
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
[super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
pspdf_ensureCalledOnlyOncePerRunloop(^{
NSLog(@"once.");
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment