change to IOAnimatedCoder

This commit is contained in:
kinarobin 2021-01-02 21:27:05 +08:00
parent 872b59e32a
commit e52686b452
3 changed files with 58 additions and 41 deletions

View File

@ -16,7 +16,6 @@
@interface SDImageCodersManager ()
@property (nonatomic, strong, nonnull) NSMutableArray<id<SDImageCoder>> *imageCoders;
@property (atomic, assign) BOOL willTerminated;
@end
@ -37,33 +36,11 @@
if (self = [super init]) {
// initialize with default coders
_imageCoders = [NSMutableArray arrayWithArray:@[[SDImageIOCoder sharedCoder], [SDImageGIFCoder sharedCoder], [SDImageAPNGCoder sharedCoder]]];
_willTerminated = NO;
#if SD_UIKIT
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(applicationWillTerminate)
name:UIApplicationWillTerminateNotification
object:nil];
#endif
#if SD_MAC
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(applicationWillTerminate)
name:NSApplicationWillTerminateNotification
object:nil];
#endif
SD_LOCK_INIT(_codersLock);
}
return self;
}
- (void)applicationWillTerminate {
self.willTerminated = YES;
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (NSArray<id<SDImageCoder>> *)coders {
SD_LOCK(_codersLock);
NSArray<id<SDImageCoder>> *coders = [_imageCoders copy];
@ -125,10 +102,6 @@
if (!data) {
return nil;
}
BOOL terminated = self.willTerminated;
if (terminated) {
return nil;
}
UIImage *image;
NSArray<id<SDImageCoder>> *coders = self.coders;
@ -146,10 +119,6 @@
if (!image) {
return nil;
}
BOOL terminated = self.willTerminated;
if (terminated) {
return nil;
}
NSArray<id<SDImageCoder>> *coders = self.coders;
for (id<SDImageCoder> coder in coders.reverseObjectEnumerator) {

View File

@ -29,6 +29,9 @@ static NSString * kSDCGImageDestinationRequestedFileSize = @"kCGImageDestination
@implementation SDImageIOCoderFrame
@end
BOOL willTerminated_;
NSLock *terminatedLock_;
@implementation SDImageIOAnimatedCoder {
size_t _width, _height;
CGImageSourceRef _imageSource;
@ -42,8 +45,40 @@ static NSString * kSDCGImageDestinationRequestedFileSize = @"kCGImageDestination
CGSize _thumbnailSize;
}
- (void)dealloc
{
+ (void)initialize {
if (self == SDImageIOAnimatedCoder.class) {
willTerminated_ = NO;
terminatedLock_ = [[NSLock alloc] init];
#if SD_UIKIT
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(applicationWillTerminate:)
name:UIApplicationWillTerminateNotification
object:nil];
#endif
#if SD_MAC
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(applicationWillTerminate:)
name:NSApplicationWillTerminateNotification
object:nil];
#endif
}
}
+ (void)applicationWillTerminate:(NSNotification *)note {
[terminatedLock_ lock];
willTerminated_ = YES;
[terminatedLock_ unlock];
}
+ (BOOL)willTerminated {
[terminatedLock_ lock];
BOOL willTerminated = willTerminated_;
[terminatedLock_ unlock];
return willTerminated;
}
- (void)dealloc {
if (_imageSource) {
CFRelease(_imageSource);
_imageSource = NULL;
@ -53,8 +88,7 @@ static NSString * kSDCGImageDestinationRequestedFileSize = @"kCGImageDestination
#endif
}
- (void)didReceiveMemoryWarning:(NSNotification *)notification
{
- (void)didReceiveMemoryWarning:(NSNotification *)notification {
if (_imageSource) {
for (size_t i = 0; i < _frameCount; i++) {
CGImageSourceRemoveCacheAtIndex(_imageSource, i);
@ -152,11 +186,17 @@ static NSString * kSDCGImageDestinationRequestedFileSize = @"kCGImageDestination
}
+ (NSTimeInterval)frameDurationAtIndex:(NSUInteger)index source:(CGImageSourceRef)source {
NSTimeInterval frameDuration = 0.1;
// Earily return when application will be terminated.
if (self.willTerminated) {
return frameDuration;
}
NSDictionary *options = @{
(__bridge NSString *)kCGImageSourceShouldCacheImmediately : @(YES),
(__bridge NSString *)kCGImageSourceShouldCache : @(YES) // Always cache to reduce CPU usage
};
NSTimeInterval frameDuration = 0.1;
CFDictionaryRef cfFrameProperties = CGImageSourceCopyPropertiesAtIndex(source, index, (__bridge CFDictionaryRef)options);
if (!cfFrameProperties) {
return frameDuration;
@ -188,6 +228,11 @@ static NSString * kSDCGImageDestinationRequestedFileSize = @"kCGImageDestination
}
+ (UIImage *)createFrameAtIndex:(NSUInteger)index source:(CGImageSourceRef)source scale:(CGFloat)scale preserveAspectRatio:(BOOL)preserveAspectRatio thumbnailSize:(CGSize)thumbnailSize options:(NSDictionary *)options {
// Earily return when application will be terminated.
if (self.willTerminated) {
return nil;
}
// Some options need to pass to `CGImageSourceCopyPropertiesAtIndex` before `CGImageSourceCreateImageAtIndex`, or ImageIO will ignore them because they parse once :)
// Parse the image properties
NSDictionary *properties = (__bridge_transfer NSDictionary *)CGImageSourceCopyPropertiesAtIndex(source, index, (__bridge CFDictionaryRef)options);
@ -375,11 +420,11 @@ static NSString * kSDCGImageDestinationRequestedFileSize = @"kCGImageDestination
CGSize thumbnailSize = CGSizeZero;
NSValue *thumbnailSizeValue = options[SDImageCoderDecodeThumbnailPixelSize];
if (thumbnailSizeValue != nil) {
#if SD_MAC
#if SD_MAC
thumbnailSize = thumbnailSizeValue.sizeValue;
#else
#else
thumbnailSize = thumbnailSizeValue.CGSizeValue;
#endif
#endif
}
_thumbnailSize = thumbnailSize;
BOOL preserveAspectRatio = YES;
@ -399,6 +444,10 @@ static NSString * kSDCGImageDestinationRequestedFileSize = @"kCGImageDestination
if (_finished) {
return;
}
// Earily return when application will be terminated.
if (self.class.willTerminated) {
return;
}
_imageData = data;
_finished = finished;

View File

@ -312,8 +312,7 @@
}
- (void)test22DoNotDecodeImageWhenApplicationWillTerminate {
/// Just create SDImageCodersManager advance
[SDImageCodersManager sharedManager];
[[SDImageCodersManager sharedManager] addCoder:SDImageIOCoder.sharedCoder];
XCTestExpectation *expectation = [self expectationWithDescription:@"doNotDecodeImageWhenApplicationWillTerminate"];
NSString *testImagePath = [[NSBundle bundleForClass:[self class]] pathForResource:@"TestImageLarge" ofType:@"png"];
NSData *testImageData = [NSData dataWithContentsOfFile:testImagePath];