Deprecate SDWebImagePrefetcher.delegateQueue, translate to use context[SDWebImageContextCallbackQueue] instead

This commit is contained in:
DreamPiggy 2023-01-09 17:45:52 +08:00
parent 5a4b4cf16d
commit 90eeb4d830
2 changed files with 73 additions and 10 deletions

View File

@ -76,20 +76,23 @@ typedef void(^SDWebImagePrefetcherCompletionBlock)(NSUInteger noOfFinishedUrls,
/**
* The options for prefetcher. Defaults to SDWebImageLowPriority.
* @deprecated Prefetcher is designed to be used shared and should not effect others. So in 5.15.0 we added API `prefetchURLs:options:context:`. If you want global control, try to use `SDWebImageOptionsProcessor` in manager level.
*/
@property (nonatomic, assign) SDWebImageOptions options;
@property (nonatomic, assign) SDWebImageOptions options API_DEPRECATED("Use individual prefetch options param instead", macos(10.10, API_TO_BE_DEPRECATED), ios(8.0, API_TO_BE_DEPRECATED), tvos(9.0, API_TO_BE_DEPRECATED), watchos(2.0, API_TO_BE_DEPRECATED));
/**
* The context for prefetcher. Defaults to nil.
* @deprecated Prefetcher is designed to be used shared and should not effect others. So in 5.15.0 we added API `prefetchURLs:options:context:`. If you want global control, try to use `SDWebImageOptionsProcessor` in `SDWebImageManager.optionsProcessor`.
*/
@property (nonatomic, copy, nullable) SDWebImageContext *context;
@property (nonatomic, copy, nullable) SDWebImageContext *context API_DEPRECATED("Use individual prefetch context param instead", macos(10.10, API_TO_BE_DEPRECATED), ios(8.0, API_TO_BE_DEPRECATED), tvos(9.0, API_TO_BE_DEPRECATED), watchos(2.0, API_TO_BE_DEPRECATED));
/**
* Queue options for prefetcher when call the progressBlock, completionBlock and delegate methods. Defaults to Main Queue.
* @note The call is asynchronously to avoid blocking target queue.
* @deprecated 5.15.0 introduce SDCallbackQueue, use that is preferred and has higher priority. The set/get to this property will translate to that instead.
* @note The call is asynchronously to avoid blocking target queue. (see SDCallbackPolicyDispatch)
* @note The delegate queue should be set before any prefetching start and may not be changed during prefetching to avoid thread-safe problem.
*/
@property (strong, nonatomic, nonnull) dispatch_queue_t delegateQueue;
@property (strong, nonatomic, nonnull) dispatch_queue_t delegateQueue API_DEPRECATED("Use SDWebImageContextCallbackQueue context param instead, see SDCallbackQueue", macos(10.10, 10.10), ios(8.0, 8.0), tvos(9.0, 9.0), watchos(2.0, 2.0));
/**
* The delegate for the prefetcher. Defaults to nil.
@ -134,6 +137,28 @@ typedef void(^SDWebImagePrefetcherCompletionBlock)(NSUInteger noOfFinishedUrls,
progress:(nullable SDWebImagePrefetcherProgressBlock)progressBlock
completed:(nullable SDWebImagePrefetcherCompletionBlock)completionBlock;
/**
* Assign list of URLs to let SDWebImagePrefetcher to queue the prefetching. It based on the image manager so the image may from the cache and network according to the `options` property.
* Prefetching is separate to each other, which means the progressBlock and completionBlock you provide is bind to the prefetching for the list of urls.
* Attention that call this will not cancel previous fetched urls. You should keep the token return by this to cancel or cancel all the prefetch.
*
* @param urls list of URLs to prefetch
* @param options The options to use when downloading the image. @see SDWebImageOptions for the possible values.
* @param context A context contains different options to perform specify changes or processes, see `SDWebImageContextOption`. This hold the extra objects which `options` enum can not hold.
* @param progressBlock block to be called when progress updates;
* first parameter is the number of completed (successful or not) requests,
* second parameter is the total number of images originally requested to be prefetched
* @param completionBlock block to be called when the current prefetching is completed
* first param is the number of completed (successful or not) requests,
* second parameter is the number of skipped requests
* @return the token to cancel the current prefetching.
*/
- (nullable SDWebImagePrefetchToken *)prefetchURLs:(nullable NSArray<NSURL *> *)urls
options:(SDWebImageOptions)options
context:(nullable SDWebImageContext *)context
progress:(nullable SDWebImagePrefetcherProgressBlock)progressBlock
completed:(nullable SDWebImagePrefetcherCompletionBlock)completionBlock;
/**
* Remove and cancel all the prefeching for the prefetcher.
*/

View File

@ -8,9 +8,16 @@
#import "SDWebImagePrefetcher.h"
#import "SDAsyncBlockOperation.h"
#import "SDCallbackQueue.h"
#import "SDInternalMacros.h"
#import <stdatomic.h>
@interface SDCallbackQueue ()
@property (nonatomic, strong, nonnull) dispatch_queue_t queue;
@end
@interface SDWebImagePrefetchToken () {
@public
// Though current implementation, `SDWebImageManager` completion block is always on main queue. But however, there is no guarantee in docs. And we may introduce config to specify custom queue in the future.
@ -30,6 +37,8 @@
@property (nonatomic, strong) NSPointerArray *loadOperations;
@property (nonatomic, strong) NSPointerArray *prefetchOperations;
@property (nonatomic, weak) SDWebImagePrefetcher *prefetcher;
@property (nonatomic, assign) SDWebImageOptions options;
@property (nonatomic, copy, nullable) SDWebImageContext *context;
@property (nonatomic, copy, nullable) SDWebImagePrefetcherCompletionBlock completionBlock;
@property (nonatomic, copy, nullable) SDWebImagePrefetcherProgressBlock progressBlock;
@ -40,6 +49,7 @@
@property (strong, nonatomic, nonnull) SDWebImageManager *manager;
@property (strong, atomic, nonnull) NSMutableSet<SDWebImagePrefetchToken *> *runningTokens;
@property (strong, nonatomic, nonnull) NSOperationQueue *prefetchQueue;
@property (strong, nonatomic, nullable) SDCallbackQueue *callbackQueue;
@end
@ -63,7 +73,6 @@
_manager = manager;
_runningTokens = [NSMutableSet set];
_options = SDWebImageLowPriority;
_delegateQueue = dispatch_get_main_queue();
_prefetchQueue = [NSOperationQueue new];
self.maxConcurrentPrefetchCount = 3;
}
@ -78,6 +87,17 @@
return self.prefetchQueue.maxConcurrentOperationCount;
}
- (void)setDelegateQueue:(dispatch_queue_t)delegateQueue {
// Deprecate and translate to SDCallbackQueue
_callbackQueue = [[SDCallbackQueue alloc] initWithDispatchQueue:delegateQueue];
_callbackQueue.policy = SDCallbackPolicyDispatch;
}
- (dispatch_queue_t)delegateQueue {
// Deprecate and translate to SDCallbackQueue
return (_callbackQueue ?: SDCallbackQueue.mainQueue).queue;
}
#pragma mark - Prefetch
- (nullable SDWebImagePrefetchToken *)prefetchURLs:(nullable NSArray<NSURL *> *)urls {
return [self prefetchURLs:urls progress:nil completed:nil];
@ -86,6 +106,14 @@
- (nullable SDWebImagePrefetchToken *)prefetchURLs:(nullable NSArray<NSURL *> *)urls
progress:(nullable SDWebImagePrefetcherProgressBlock)progressBlock
completed:(nullable SDWebImagePrefetcherCompletionBlock)completionBlock {
return [self prefetchURLs:urls options:self.options context:self.context progress:progressBlock completed:completionBlock];
}
- (nullable SDWebImagePrefetchToken *)prefetchURLs:(nullable NSArray<NSURL *> *)urls
options:(SDWebImageOptions)options
context:(nullable SDWebImageContext *)context
progress:(nullable SDWebImagePrefetcherProgressBlock)progressBlock
completed:(nullable SDWebImagePrefetcherCompletionBlock)completionBlock {
if (!urls || urls.count == 0) {
if (completionBlock) {
completionBlock(0, 0);
@ -95,6 +123,8 @@
SDWebImagePrefetchToken *token = [SDWebImagePrefetchToken new];
token.prefetcher = self;
token.urls = urls;
token.options = options;
token.context = context;
token->_skippedCount = 0;
token->_finishedCount = 0;
token->_totalCount = token.urls.count;
@ -117,7 +147,7 @@
if (!self || asyncOperation.isCancelled) {
return;
}
id<SDWebImageOperation> operation = [self.manager loadImageWithURL:url options:self.options context:self.context progress:nil completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, SDImageCacheType cacheType, BOOL finished, NSURL * _Nullable imageURL) {
id<SDWebImageOperation> operation = [self.manager loadImageWithURL:url options:token.options context:token.context progress:nil completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, SDImageCacheType cacheType, BOOL finished, NSURL * _Nullable imageURL) {
@strongify(self);
if (!self) {
return;
@ -173,14 +203,18 @@
NSUInteger tokenTotalCount = [self tokenTotalCount];
NSUInteger finishedCount = atomic_load_explicit(&(token->_finishedCount), memory_order_relaxed);
NSUInteger totalCount = token->_totalCount;
dispatch_async(self.delegateQueue, ^{
SDCallbackQueue *queue = token.context[SDWebImageContextCallbackQueue];
if (!queue) {
queue = self.callbackQueue;
}
[(queue ?: SDCallbackQueue.mainQueue) async:^{
if (shouldCallDelegate) {
[self.delegate imagePrefetcher:self didPrefetchURL:url finishedCount:tokenFinishedCount totalCount:tokenTotalCount];
}
if (token.progressBlock) {
token.progressBlock(finishedCount, totalCount);
}
});
}];
}
- (void)callCompletionBlockForToken:(SDWebImagePrefetchToken *)token {
@ -192,14 +226,18 @@
NSUInteger tokenSkippedCount = [self tokenSkippedCount];
NSUInteger finishedCount = atomic_load_explicit(&(token->_finishedCount), memory_order_relaxed);
NSUInteger skippedCount = atomic_load_explicit(&(token->_skippedCount), memory_order_relaxed);
dispatch_async(self.delegateQueue, ^{
SDCallbackQueue *queue = token.context[SDWebImageContextCallbackQueue];
if (!queue) {
queue = self.callbackQueue;
}
[(queue ?: SDCallbackQueue.mainQueue) async:^{
if (shoulCallDelegate) {
[self.delegate imagePrefetcher:self didFinishWithTotalCount:tokenTotalCount skippedCount:tokenSkippedCount];
}
if (token.completionBlock) {
token.completionBlock(finishedCount, skippedCount);
}
});
}];
}
#pragma mark - Helper