diff --git a/SDWebImage/SDWebImageCodersManager.h b/SDWebImage/SDWebImageCodersManager.h index 0b44e297..fc40e5f8 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 8f33b816..47c4f9a6 100644 --- a/SDWebImage/SDWebImageCodersManager.m +++ b/SDWebImage/SDWebImageCodersManager.m @@ -17,10 +17,12 @@ #import "UIImage+WebCache.h" #import "SDWebImageDefine.h" +#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 @@ -38,11 +40,12 @@ - (instancetype)init { if (self = [super init]) { // initialize with default coders - _mutableCoders = [@[[SDWebImageImageIOCoder sharedCoder], [SDWebImageGIFCoder sharedCoder], [SDWebImageAPNGCoder sharedCoder]] mutableCopy]; + NSMutableArray> *mutableCoders = [@[[SDWebImageImageIOCoder sharedCoder], [SDWebImageGIFCoder sharedCoder], [SDWebImageAPNGCoder 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; } @@ -50,36 +53,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; } @@ -88,7 +91,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; } @@ -101,7 +107,10 @@ return nil; } UIImage *image; - 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]) { image = [coder decodedImageWithData:data options:options]; break; @@ -115,7 +124,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 options:nil]; }