I'm trying to modify a shared __block BOOL
variable for the purposes of flagging of execution to proceed. I implemented it successfully by creating an object that encapsulates the BOOL
variable, but when sending the block inline, there are issues--I must create a local variable for the block and explicitly reference the BOOL
variable inside of it (marked 1A in code sample). Any ideas how to make the - (void)primitive_cancellable_dispatch_after:(dispatch_time_t)delay block:(MyBlock)block stop:(BOOL*)stop
method work without this requirement from the call site? It seems that the variable is not being captured unless it is being assigned locally and referenced. In general, at what point is the variable captured if not being explicitly referenced locally?
dispatch_time_t delay = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC));
__block BOOL stop;
// =============== 1A ===============
MyBlock primitiveBlock = ^{
NSLog(@"Ran primitive implementation via assignment. (stop: %@ / %p)", @(stop), &stop); // stop only "captured" when referencing within a locally assigned block, if this line is commented out, stop isn't updated
};
// =============== 1A ===============
[self primitive_cancellable_dispatch_after:delay block:^{
NSLog(@"Ran primitive implementation via inline. (stop: %@ / %p)", @(stop), &stop);
} stop:&stop];
__block Task *task = [self reference_cancellable_dispatch_after:delay block:^{
NSLog(@"Ran reference implementation: (task.shouldCancel: %@)",@(task.shouldCancel));
}];
task.shouldCancel = NO; // works as expected
stop = NO; // stop isn't updated as expected, when checking value within "primitive_cancellable_dispatch_after", always returns no
}
- (void)primitive_cancellable_dispatch_after:(dispatch_time_t)delay block:(MyBlock)block stop:(BOOL*)stop {
dispatch_after(delay, dispatch_get_main_queue(), ^{
BOOL shouldStop = *stop; // stop doesn't seem to resolving correctly, stop is always "NO", unless assigning a local block outside
NSLog(@"Checking primitive stop (shouldStop: %@ / %p)", @(shouldStop), stop);
if(!shouldStop && block) {
block();
NSLog(@"Checking primitive stop (shouldStop: %@ / %p)", @(shouldStop), stop);
}
});
}
/*@interface Task : NSObject
@property (nonatomic, assign) BOOL shouldCancel;
@property (nonatomic, strong) Task *task;
@end
@implementation Task
@end*/
- (Task*)reference_cancellable_dispatch_after:(dispatch_time_t)delay block:(MyBlock)block {
Task *task = [Task new];
dispatch_after(delay, dispatch_get_main_queue(), ^{
if(!task.shouldCancel && block) {
block();
}
});
return task;
}