Skip to content

Instantly share code, notes, and snippets.

@zats
Last active December 15, 2015 05:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zats/5212898 to your computer and use it in GitHub Desktop.
Save zats/5212898 to your computer and use it in GitHub Desktop.
Dynamic category icons – Foursquare approach
- (AFHTTPRequestOperation *)imageFetchOperationForCategoryWithURL:(NSURL *)URL success:(void(^)(AFHTTPRequestOperation *operation, id response))success failure:(void(^)(AFHTTPRequestOperation *operation, NSError *error))failure
{
static NSString *categoriesCacheDirectory;
static NSCache *inMemoryCache;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
inMemoryCache = [[NSCache alloc] init];
categoriesCacheDirectory = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
categoriesCacheDirectory = [categoriesCacheDirectory stringByAppendingPathComponent:@"location_icons"];
});
NSString *urlHash = [[URL absoluteString] MD5Sum];
__block UIImage *image = nil;
// 1. We check in memory cache
image = [inMemoryCache objectForKey:urlHash];
if (image) {
if (success) {
success(nil, image);
}
return nil;
}
// 2. Trying to find image locally and pull it to cache
NSString *filePath = [[categoriesCacheDirectory stringByAppendingPathComponent:urlHash] stringByAppendingPathExtension:@"png"];
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
NSData *data = [NSData dataWithContentsOfFile:filePath];
image = [UIImage imageWithData:data];
// 2.1 Put it in the cache
[inMemoryCache setObject:image
forKey:urlHash
cost:0];
if (success) {
success(nil, image);
}
return nil;
}
// 3. Finally we have to pull the image from the network and compose custom icon
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
AFHTTPRequestOperation *operation = [self HTTPRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject) {
// 3.0 Sanity
if (![responseObject isKindOfClass:[NSData class]]) {
if (failure) {
failure(operation, [NSError errorWithDomain:NSCocoaErrorDomain
code:0
userInfo:@{ NSLocalizedDescriptionKey : [NSString stringWithFormat:@"Unexpected response type, expected NSData, got %@", [responseObject class]] }]);
}
return;
}
// 3.1 Make sure cache directory exist
BOOL isDirectory = NO;
BOOL isExist = [[NSFileManager defaultManager] fileExistsAtPath:categoriesCacheDirectory
isDirectory:&isDirectory];
if (!isExist || !isDirectory) {
NSDictionary *attributes = nil;
[[NSFileManager defaultManager] createDirectoryAtPath:categoriesCacheDirectory
withIntermediateDirectories:YES
attributes:attributes
error:nil];
}
// 3.2 Compose custom image
image = TPXCustomCategoryImageFromImageMaskData( responseObject );
NSData *data = UIImagePNGRepresentation(image);
// 3.3 Save to cache directory
[data writeToFile:filePath
atomically:NO];
// 3.4 Cache it!
[inMemoryCache setObject:image
forKey:urlHash
cost:0];
if (success) {
success(operation, image);
}
} failure:failure];
[self enqueueHTTPRequestOperation:operation];
return operation;
}
UIImage *TPXCustomCategoryImageFromImageMaskData(NSData *imageData)
{
UIImage *iconImage = [UIImage imageWithData:imageData];
CGSize imageSize = CGSizeMake(50, 50);
CGRect imageFrame = (CGRect){CGPointZero, imageSize};
CGFloat scale = [UIScreen mainScreen].scale;
UIGraphicsBeginImageContextWithOptions(imageSize, NO, scale);
CGContextRef context = UIGraphicsGetCurrentContext();
CGRect outlineFrame = CGRectInset(imageFrame, 1, 1);
UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRoundedRect:outlineFrame
byRoundingCorners:UIRectCornerAllCorners
cornerRadii:CGSizeMake(6, 6)];
[[UIColor colorWithHue:0.056f
saturation:0.030f
brightness:0.773f
alpha:1.000f] setStroke];
[[UIColor colorWithHue:0.083f
saturation:0.041f
brightness:0.961f
alpha:1.000f] setFill];
bezierPath.lineWidth = 1;
[bezierPath stroke];
[bezierPath fill];
[[UIColor clearColor] setStroke];
// Create a mask
CGImageRef originalImageRef = iconImage.CGImage;
CGContextTranslateCTM(context, 0, CGRectGetHeight(imageFrame));
CGContextScaleCTM(context, 1.0, -1.0);
CGRect centredImageRect = (CGRect){CGPointZero, imageSize};
centredImageRect = CGRectInset(centredImageRect, 5, 5);
CGContextClipToMask(context, centredImageRect, originalImageRef);
// Fill it
[[UIColor colorWithWhite:0.545f
alpha:1.000f] setFill];
CGContextFillRect(context, imageFrame);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment