Merge pull request #3149 from kinarobin/fix-ImageIO-encode/decode-crash
Don't encode/decode image when app will terminated
This commit is contained in:
commit
aa2e264ffb
|
@ -41,16 +41,14 @@
|
|||
return self;
|
||||
}
|
||||
|
||||
- (NSArray<id<SDImageCoder>> *)coders
|
||||
{
|
||||
- (NSArray<id<SDImageCoder>> *)coders {
|
||||
SD_LOCK(_codersLock);
|
||||
NSArray<id<SDImageCoder>> *coders = [_imageCoders copy];
|
||||
SD_UNLOCK(_codersLock);
|
||||
return coders;
|
||||
}
|
||||
|
||||
- (void)setCoders:(NSArray<id<SDImageCoder>> *)coders
|
||||
{
|
||||
- (void)setCoders:(NSArray<id<SDImageCoder>> *)coders {
|
||||
SD_LOCK(_codersLock);
|
||||
[_imageCoders removeAllObjects];
|
||||
if (coders.count) {
|
||||
|
|
|
@ -29,6 +29,9 @@ static NSString * kSDCGImageDestinationRequestedFileSize = @"kCGImageDestination
|
|||
@implementation SDImageIOCoderFrame
|
||||
@end
|
||||
|
||||
static BOOL willTerminated_;
|
||||
static 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);
|
||||
|
@ -188,6 +222,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 +414,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 +438,10 @@ static NSString * kSDCGImageDestinationRequestedFileSize = @"kCGImageDestination
|
|||
if (_finished) {
|
||||
return;
|
||||
}
|
||||
// Earily return when application will be terminated.
|
||||
if (self.class.willTerminated) {
|
||||
return;
|
||||
}
|
||||
_imageData = data;
|
||||
_finished = finished;
|
||||
|
||||
|
|
|
@ -311,6 +311,26 @@
|
|||
}
|
||||
}
|
||||
|
||||
- (void)test22DoNotDecodeImageWhenApplicationWillTerminate {
|
||||
[[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];
|
||||
[[SDImageCache sharedImageCache] storeImageDataToDisk:testImageData forKey:@"TestImageLarge"];
|
||||
NSOperation *operation = [[SDImageCache sharedImageCache] queryCacheOperationForKey:@"TestImageLarge" done:^(UIImage *image, NSData *data, SDImageCacheType cacheType) {
|
||||
expect(data).to.equal(testImageData);
|
||||
expect(image).to.beNil;
|
||||
[[SDImageCache sharedImageCache] removeImageForKey:@"TestImageLarge" withCompletion:^{
|
||||
[expectation fulfill];
|
||||
}];
|
||||
}];
|
||||
expect(operation).toNot.beNil;
|
||||
[operation start];
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:UIApplicationWillTerminateNotification object:nil];
|
||||
|
||||
[self waitForExpectationsWithCommonTimeout];
|
||||
}
|
||||
|
||||
#pragma mark - Utils
|
||||
|
||||
- (void)verifyCoder:(id<SDImageCoder>)coder
|
||||
|
|
Loading…
Reference in New Issue