Skip to content

Instantly share code, notes, and snippets.

@hollance
Last active June 3, 2021 07:39
Show Gist options
  • Save hollance/6327699 to your computer and use it in GitHub Desktop.
Save hollance/6327699 to your computer and use it in GitHub Desktop.
You cannot easily cancel Objective-C blocks that are running on a background queue. One possible solution is to let the block capture an object -- the so-called "cancel ticket" -- that determines whether it should stop or not. Whoever holds the ticket can call [ticket cancel] to stop the block. Of course, this does require the block to periodica…
// Shows how to use the cancel ticket to abort the async block.
#import "ExampleViewController.h"
#import "MHCancelTicket.h"
@implementation ExampleViewController
{
MHCancelTicket *_cancelTicket;
}
- (IBAction)startAction:(id)sender
{
if (_cancelTicket == nil)
{
_cancelTicket = [self startExpensiveOperation];
}
}
- (IBAction)stopAction:(id)sender
{
if (_cancelTicket != nil)
{
[_cancelTicket cancel];
_cancelTicket = nil;
}
}
- (MHCancelTicket *)startExpensiveOperation
{
MHCancelTicket *ticket = [MHCancelTicket cancelTicket];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^
{
while (!ticket.isCancelled)
{
// do your computations here!
}
});
return ticket;
}
@end
@interface MHCancelTicket : NSObject
@property (atomic, assign, readonly) BOOL isCancelled;
+ (instancetype)cancelTicket;
- (void)cancel;
@end
#import "MHCancelTicket.h"
@interface MHCancelTicket ()
@property (atomic, assign, readwrite) BOOL isCancelled;
@end
@implementation MHCancelTicket
+ (instancetype)cancelTicket
{
return [[[self class] alloc] init];
}
- (void)cancel
{
self.isCancelled = YES;
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment