Skip to content

Instantly share code, notes, and snippets.

@jtbandes
Last active December 10, 2015 20:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jtbandes/4488175 to your computer and use it in GitHub Desktop.
Save jtbandes/4488175 to your computer and use it in GitHub Desktop.
#import "JTAsynchronousImageView.h"
@interface JTAsynchronousImageView ()
@property (nonatomic, copy) void (^loadingBlock)(JTAsynchronousImageViewLoadCompletionHandler completionHandler);
@property (nonatomic, strong) void (^cancellationBlock)();
@end
@implementation JTAsynchronousImageView {
// Queue for the image that is currently loading.
dispatch_queue_t _currentQueue;
}
- (void)awakeFromNib
{
self.placeholderImage = self.image;
}
- (void)loadWithBlock:(void (^)(JTAsynchronousImageViewLoadCompletionHandler completionHandler))loadingBlock
{
if (!_loadingQueue) {
_loadingQueue = dispatch_queue_create("net.bandes-storch.Draw.JTAsynchronousImageView", DISPATCH_QUEUE_SERIAL);
}
// Once the cancellation block has been submitted, the image has either set cancelled=YES,
// before execution of the completion block, or it has successfully loaded.
if (_cancellationBlock) NSLog(@"Cancelling load %@", self);
if (_cancellationBlock) dispatch_async(_currentQueue, _cancellationBlock);
self.image = _placeholderImage;
_currentQueue = _loadingQueue;
_loadingBlock = [loadingBlock copy];
JTAsynchronousImageView *__weak bself = self;
BOOL __block cancelled = NO;
dispatch_async(_loadingQueue, ^{
typeof(bself) __strong self = bself;
if (!self) return;
self.loadingBlock(^(UIImage *image) {
// Continue asynchronously, allowing the cancellation block to run if it has already been submitted
dispatch_async(_loadingQueue, ^{
typeof(bself) __strong self = bself;
if (!self) return;
self.cancellationBlock = nil;
self.loadingBlock = nil;
if (cancelled) return;
dispatch_async(dispatch_get_main_queue(), ^{
typeof(bself) __strong self = bself;
if (!self) return;
self.image = image;
[self invalidateIntrinsicContentSize];
[self.superview setNeedsLayout];
});
});
});
});
_cancellationBlock = [^{
cancelled = YES;
} copy];
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment