Skip to content

Instantly share code, notes, and snippets.

@SteveTrewick
Last active August 29, 2015 14:03
Show Gist options
  • Save SteveTrewick/f2f67bc2e40b86f40df9 to your computer and use it in GitHub Desktop.
Save SteveTrewick/f2f67bc2e40b86f40df9 to your computer and use it in GitHub Desktop.
A cleaner version of the previous code without some of the __weak, __strong line noise. Recursive completion blocks in ObjC using some higher order functions.
#import <Foundation/Foundation.h>
typedef void(^CompletionHandler)(id connection, id result, NSError * error);
typedef BOOL(^Counter)();
typedef void(^RequestWrapperComp)();
@interface SMRequestFoo : NSObject
+(void)
request :(id ) thing
completion:(CompletionHandler) completion;
@end
@implementation SMRequestFoo
+(void)
request :(id ) thing
completion:(CompletionHandler) completion
{
static int count_through = 0;
NSError * error = count_through > 3 ? nil: [NSError errorWithDomain:@"Domain" code:42 userInfo:nil];
id result = nil;
id connection = nil;
count_through++;
// API I'm mocking out here calls completions on main Q
dispatch_async(dispatch_get_main_queue(),^{
completion(connection, result, error);
});
}
@end
int main(int argc, const char * argv[])
{
@autoreleasepool {
dispatch_queue_t requestQ = dispatch_queue_create("requestQ", 0);
Counter (^CounterBuilder)(int) = ^Counter(int max){
return ^BOOL{
static int retries = 0;
return retries++ >= max ? YES : NO;
};
};
int (^backOffLinear)() = ^int{
static int delay = 0;
return delay++;
};
RequestWrapperComp (^RequestWrapperBuilderComp)(id, CompletionHandler) = (
^RequestWrapperComp(id obj, CompletionHandler ch){
return ^void{
[SMRequestFoo
request : obj
completion: ch
];
};
}
);
__block RequestWrapperComp reqcomp = nil;
__block Counter retry_count_exceeded = nil;
__block CompletionHandler completion_handler = (
^(id connection, id result, NSError * error)
{
if (error) {
if( retry_count_exceeded() ) {
NSLog(@"Failed at max retries, we're done here");
}
else {
NSLog(@"Retry...");
// Get off the main Q
dispatch_async( requestQ, ^{
sleep( backOffLinear() ); // hmmmmm...
reqcomp();
});
}
}
else { NSLog(@"OK all good now, moving on for other things"); }
}
);
reqcomp = RequestWrapperBuilderComp(nil, completion_handler);
retry_count_exceeded = CounterBuilder(4);
reqcomp();
// Keep on truckin'
[[NSRunLoop currentRunLoop] run];
}
return 0;
}
/* **
2014-06-26 10:10:19.302 completion_retry_spike_1[5167:303] Retry...
2014-06-26 10:10:19.304 completion_retry_spike_1[5167:303] Retry...
2014-06-26 10:10:20.305 completion_retry_spike_1[5167:303] Retry...
2014-06-26 10:10:22.307 completion_retry_spike_1[5167:303] Retry...
2014-06-26 10:10:25.309 completion_retry_spike_1[5167:303] OK all good now, moving on for other things
** */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment