diff --git a/SDWebImage/SDWebImageCodersManager.h b/SDWebImage/SDWebImageCodersManager.h index 7523ecba..ca687483 100644 --- a/SDWebImage/SDWebImageCodersManager.h +++ b/SDWebImage/SDWebImageCodersManager.h @@ -39,7 +39,7 @@ /** All coders in coders manager. The coders array is a priority queue, which means the later added coder will have the highest priority */ -@property (nonatomic, strong, readwrite, nullable) NSArray> *coders; +@property (nonatomic, copy, readwrite, nullable) NSArray> *coders; /** Add a new coder to the end of coders array. Which has the highest priority. diff --git a/SDWebImage/SDWebImageCodersManager.m b/SDWebImage/SDWebImageCodersManager.m index 45595759..79c3bff5 100644 --- a/SDWebImage/SDWebImageCodersManager.m +++ b/SDWebImage/SDWebImageCodersManager.m @@ -13,10 +13,12 @@ #import "SDWebImageWebPCoder.h" #endif +#define LOCK(lock) dispatch_semaphore_wait(lock, DISPATCH_TIME_FOREVER); +#define UNLOCK(lock) dispatch_semaphore_signal(lock); + @interface SDWebImageCodersManager () -@property (strong, nonatomic, nonnull) NSMutableArray* mutableCoders; -@property (strong, nonatomic, nullable) dispatch_queue_t mutableCodersAccessQueue; +@property (nonatomic, strong, nonnull) dispatch_semaphore_t codersLock; @end @@ -34,11 +36,12 @@ - (instancetype)init { if (self = [super init]) { // initialize with default coders - _mutableCoders = [@[[SDWebImageImageIOCoder sharedCoder]] mutableCopy]; + NSMutableArray> *mutableCoders = [@[[SDWebImageImageIOCoder sharedCoder]] mutableCopy]; #ifdef SD_WEBP - [_mutableCoders addObject:[SDWebImageWebPCoder sharedCoder]]; + [mutableCoders addObject:[SDWebImageWebPCoder sharedCoder]]; #endif - _mutableCodersAccessQueue = dispatch_queue_create("com.hackemist.SDWebImageCodersManager", DISPATCH_QUEUE_CONCURRENT); + _coders = [mutableCoders copy]; + _codersLock = dispatch_semaphore_create(1); } return self; } @@ -46,36 +49,36 @@ #pragma mark - Coder IO operations - (void)addCoder:(nonnull id)coder { - if ([coder conformsToProtocol:@protocol(SDWebImageCoder)]) { - dispatch_barrier_sync(self.mutableCodersAccessQueue, ^{ - [self.mutableCoders addObject:coder]; - }); + if (![coder conformsToProtocol:@protocol(SDWebImageCoder)]) { + return; } + LOCK(self.codersLock); + NSMutableArray> *mutableCoders = [self.coders mutableCopy]; + if (!mutableCoders) { + mutableCoders = [NSMutableArray array]; + } + [mutableCoders addObject:coder]; + self.coders = [mutableCoders copy]; + UNLOCK(self.codersLock); } - (void)removeCoder:(nonnull id)coder { - dispatch_barrier_sync(self.mutableCodersAccessQueue, ^{ - [self.mutableCoders removeObject:coder]; - }); -} - -- (NSArray> *)coders { - __block NSArray> *sortedCoders = nil; - dispatch_sync(self.mutableCodersAccessQueue, ^{ - sortedCoders = (NSArray> *)[[[self.mutableCoders copy] reverseObjectEnumerator] allObjects]; - }); - return sortedCoders; -} - -- (void)setCoders:(NSArray> *)coders { - dispatch_barrier_sync(self.mutableCodersAccessQueue, ^{ - self.mutableCoders = [coders mutableCopy]; - }); + if (![coder conformsToProtocol:@protocol(SDWebImageCoder)]) { + return; + } + LOCK(self.codersLock); + NSMutableArray> *mutableCoders = [self.coders mutableCopy]; + [mutableCoders removeObject:coder]; + self.coders = [mutableCoders copy]; + UNLOCK(self.codersLock); } #pragma mark - SDWebImageCoder - (BOOL)canDecodeFromData:(NSData *)data { - for (id coder in self.coders) { + LOCK(self.codersLock); + NSArray> *coders = self.coders; + UNLOCK(self.codersLock); + for (id coder in coders.reverseObjectEnumerator) { if ([coder canDecodeFromData:data]) { return YES; } @@ -84,7 +87,10 @@ } - (BOOL)canEncodeToFormat:(SDImageFormat)format { - for (id coder in self.coders) { + LOCK(self.codersLock); + NSArray> *coders = self.coders; + UNLOCK(self.codersLock); + for (id coder in coders.reverseObjectEnumerator) { if ([coder canEncodeToFormat:format]) { return YES; } @@ -93,10 +99,10 @@ } - (UIImage *)decodedImageWithData:(NSData *)data { - if (!data) { - return nil; - } - for (id coder in self.coders) { + LOCK(self.codersLock); + NSArray> *coders = self.coders; + UNLOCK(self.codersLock); + for (id coder in coders.reverseObjectEnumerator) { if ([coder canDecodeFromData:data]) { return [coder decodedImageWithData:data]; } @@ -110,7 +116,10 @@ if (!image) { return nil; } - for (id coder in self.coders) { + LOCK(self.codersLock); + NSArray> *coders = self.coders; + UNLOCK(self.codersLock); + for (id coder in coders.reverseObjectEnumerator) { if ([coder canDecodeFromData:*data]) { return [coder decompressedImageWithImage:image data:data options:optionsDict]; } @@ -122,7 +131,10 @@ if (!image) { return nil; } - for (id coder in self.coders) { + LOCK(self.codersLock); + NSArray> *coders = self.coders; + UNLOCK(self.codersLock); + for (id coder in coders.reverseObjectEnumerator) { if ([coder canEncodeToFormat:format]) { return [coder encodedDataWithImage:image format:format]; }