TwitterImagePipeline/Project/TIPImageDownloadInternalContext.m (110 lines of code) (raw):

// // TIPImageDownloadInternalContext.m // TwitterImagePipeline // // Created on 10/14/15. // Copyright © 2020 Twitter. All rights reserved. // #import "TIP_Project.h" #import "TIPError.h" #import "TIPGlobalConfiguration+Project.h" #import "TIPImageDownloadInternalContext.h" #import "TIPTiming.h" NS_ASSUME_NONNULL_BEGIN @implementation TIPImageDownloadInternalContext - (instancetype)init { self = [super init]; if (self) { _delegates = [NSMutableArray array]; } return self; } - (NSUInteger)delegateCount { return _delegates.count; } - (void)reset { TIPAssert(!_flags.didComplete); TIPAssert(!_progressStateError); _response = nil; _contentLength = 0; _hydratedRequest = nil; _authorization = nil; memset(&_flags, 0, sizeof(_flags)); } - (nullable TIPImageFetchOperation *)associatedImageFetchOperation { for (id<TIPImageDownloadDelegate> delegate in _delegates) { if ([delegate isKindOfClass:[TIPImageFetchOperation class]]) { return (id)delegate; } } return nil; } - (nullable id<TIPImageDownloadDelegate>)firstDelegate { return _delegates.firstObject; } - (NSOperationQueuePriority)downloadPriority { NSOperationQueuePriority pri = NSOperationQueuePriorityVeryLow + 1; for (id<TIPImageDownloadDelegate> delegate in _delegates) { const NSOperationQueuePriority delegatePriority = delegate.imageDownloadRequest.imageDownloadPriority; pri = MAX(pri, delegatePriority); } return pri; } - (BOOL)containsDelegate:(id<TIPImageDownloadDelegate>)delegate { return [_delegates containsObject:delegate]; } - (void)addDelegate:(id<TIPImageDownloadDelegate>)delegate { [_delegates addObject:delegate]; } - (void)removeDelegate:(id<TIPImageDownloadDelegate>)delegate { NSUInteger count = _delegates.count; [_delegates removeObject:delegate]; if (count > _delegates.count) { id<TIPImageFetchDownload> download = _download; [TIPImageDownloadInternalContext executeDelegate:delegate suspendingQueue:NULL block:^(id<TIPImageDownloadDelegate> blockDelegate) { [blockDelegate imageDownload:(id)download didCompleteWithPartialImage:nil lastModified:nil byteSize:0 imageType:nil image:nil imageData:nil imageRenderLatency:0.0 statusCode:0 error:[NSError errorWithDomain:TIPImageFetchErrorDomain code:TIPImageFetchErrorCodeCancelled userInfo:nil]]; }]; } } - (void)executePerDelegateSuspendingQueue:(nullable dispatch_queue_t)queue block:(void(^)(id<TIPImageDownloadDelegate>))block { for (id<TIPImageDownloadDelegate> delegate in _delegates) { [TIPImageDownloadInternalContext executeDelegate:delegate suspendingQueue:queue block:block]; } } + (void)executeDelegate:(id<TIPImageDownloadDelegate>)delegate suspendingQueue:(nullable dispatch_queue_t)queue block:(void (^)(id<TIPImageDownloadDelegate>))block { dispatch_queue_t delegateQueue = [delegate respondsToSelector:@selector(imageDownloadDelegateQueue)] ? delegate.imageDownloadDelegateQueue : NULL; if (delegateQueue) { if (queue) { dispatch_suspend(queue); } tip_dispatch_async_autoreleasing(delegateQueue, ^{ block(delegate); if (queue) { dispatch_resume(queue); } }); } else { block(delegate); } } @end NS_ASSUME_NONNULL_END