From 6201b36f0aee92e2208dc270e09ae6abd1c300cd Mon Sep 17 00:00:00 2001 From: Panayot Cankov Date: Fri, 13 May 2016 16:47:59 +0300 Subject: [PATCH] Add UIImage extensions for thread safe async loading and decoding --- .../TNSWidgets.xcodeproj/project.pbxproj | 2 + ios/TNSWidgets/TNSWidgets/UIImage+TNSBlocks.h | 3 + ios/TNSWidgets/TNSWidgets/UIImage+TNSBlocks.m | 60 +++++++++++-------- 3 files changed, 41 insertions(+), 24 deletions(-) diff --git a/ios/TNSWidgets/TNSWidgets.xcodeproj/project.pbxproj b/ios/TNSWidgets/TNSWidgets.xcodeproj/project.pbxproj index 80fb9c3cc..d2043b482 100644 --- a/ios/TNSWidgets/TNSWidgets.xcodeproj/project.pbxproj +++ b/ios/TNSWidgets/TNSWidgets.xcodeproj/project.pbxproj @@ -382,6 +382,7 @@ F98F5CC51CD0EFEA00978308 /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; F98F5CC61CD0EFEA00978308 /* Build configuration list for PBXNativeTarget "TNSWidgetsTests" */ = { isa = XCConfigurationList; @@ -390,6 +391,7 @@ F98F5CC81CD0EFEA00978308 /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; diff --git a/ios/TNSWidgets/TNSWidgets/UIImage+TNSBlocks.h b/ios/TNSWidgets/TNSWidgets/UIImage+TNSBlocks.h index cdcbd3361..9e67228be 100644 --- a/ios/TNSWidgets/TNSWidgets/UIImage+TNSBlocks.h +++ b/ios/TNSWidgets/TNSWidgets/UIImage+TNSBlocks.h @@ -20,4 +20,7 @@ */ + (UIImage*) tns_safeImageNamed: (NSString*) name; ++ (void) tns_decodeImageWithData: (NSData*) data completion: (void (^) (UIImage*))callback; ++ (void) tns_decodeImageWidthContentsOfFile: (NSString*) file completion: (void (^) (UIImage*))callback; + @end diff --git a/ios/TNSWidgets/TNSWidgets/UIImage+TNSBlocks.m b/ios/TNSWidgets/TNSWidgets/UIImage+TNSBlocks.m index 1fa7162f2..155c9a9f1 100644 --- a/ios/TNSWidgets/TNSWidgets/UIImage+TNSBlocks.m +++ b/ios/TNSWidgets/TNSWidgets/UIImage+TNSBlocks.m @@ -6,24 +6,13 @@ // Copyright © 2016 Telerik A D. All rights reserved. // #import +#import #import "UIImage+TNSBlocks.h" @implementation UIImage (TNSBlocks) -static NSLock* image_lock_handle; static dispatch_queue_t image_queue; - -void image_lock() { - if (image_lock_handle) { - [image_lock_handle lock]; - } -} - -void image_unlock() { - if (image_lock_handle) { - [image_lock_handle unlock]; - } -} +static NSLock* image_lock_handle; + (void) initialize { image_queue = dispatch_queue_create("org.nativescript.TNSWidgets.image", NULL); @@ -35,20 +24,21 @@ void image_unlock() { } } -- (void) tns_decompressImage { - UIGraphicsBeginImageContext(CGSizeMake(1, 1)); - [self drawAtPoint:CGPointZero]; - UIGraphicsEndImageContext(); +- (void) tns_forceDecode { + CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); + CGContextRef context = CGBitmapContextCreate(NULL, 1, 1, 8, 0, colorSpace, kCGImageAlphaPremultipliedFirst); + CGContextDrawImage(context, CGRectMake(0, 0, 1, 1), [self CGImage]); + CGContextRelease(context); + CGColorSpaceRelease(colorSpace); } + (void) tns_safeDecodeImageNamed: (NSString*) name completion: (void (^) (UIImage*))callback { dispatch_async(image_queue, ^(void){ - image_lock(); + [image_lock_handle lock]; UIImage* image = [UIImage imageNamed: name]; - if (image) { - [image tns_decompressImage]; - } - image_unlock(); + [image_lock_handle unlock]; + [image tns_forceDecode]; + dispatch_async(dispatch_get_main_queue(), ^(void) { callback(image); }); @@ -56,10 +46,32 @@ void image_unlock() { } + (UIImage*) tns_safeImageNamed: (NSString*) name { - image_lock(); + [image_lock_handle lock]; UIImage* image = [UIImage imageNamed: name]; - image_unlock(); + [image_lock_handle unlock]; return image; } ++ (void) tns_decodeImageWithData: (NSData*) data completion: (void (^) (UIImage*))callback { + dispatch_async(image_queue, ^(void) { + UIImage* image = [UIImage imageWithData: data]; + [image tns_forceDecode]; + + dispatch_async(dispatch_get_main_queue(), ^(void) { + callback(image); + }); + }); +} + ++ (void) tns_decodeImageWidthContentsOfFile: (NSString*) file completion: (void (^) (UIImage*))callback { + dispatch_async(image_queue, ^(void) { + UIImage* image = [UIImage imageWithContentsOfFile: file]; + [image tns_forceDecode]; + + dispatch_async(dispatch_get_main_queue(), ^(void) { + callback(image); + }); + }); +} + @end