Last active
December 15, 2015 19:58
-
-
Save fbartho/5314747 to your computer and use it in GitHub Desktop.
Example integration of FBStackableURLCache
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Note: Not pictured here: logic specific to the system that nukes the UICache.db if we know the content is probably out of date | |
/** | |
* Make our base URL cache to the similar details as the standard default sharedURLCache in case someone is using it. | |
* From Apple Docs for NSURLCache: | |
* <li>Memory capacity: 4 megabytes (4 * 1024 * 1024 bytes) | |
* <li>Disk capacity: 20 megabytes (20 * 1024 * 1024 bytes) | |
* <li>Disk path: <nobr>(user home directory)/Library/Caches/(current application name)</nobr> | |
* <br>where: | |
* <br>user home directory is determined by calling | |
* <tt>NSHomeDirectory()</tt> | |
* <br>current application name is determined by calling | |
* <tt>[[NSProcessInfo processInfo] processName]</tt> | |
* </ul> | |
*/ | |
FBStackableURLCache * baseCache = [[FBStackableURLCache alloc] initWithMemoryCapacity: (2 * 1024 * 1024) | |
diskCapacity: (10 * 1024 * 1024) | |
diskPath: @"Cache.db"]; | |
[FBStackableURLCache setSharedURLCacheStack:baseCache]; | |
WebviewAssetCache = [[NSURLCache alloc] initWithMemoryCapacity: (2 * 1024 * 1024) | |
diskCapacity: (20 * 1024 * 1024) | |
diskPath: @"UICache.db"]; | |
ImageAssetCache = [[NSURLCache alloc] initWithMemoryCapacity: (2 * 1024 * 1024) //No Point in making this bigger because NSURLCache won't keep files in memory if they're over 50kb | |
diskCapacity: (30 * 1024 * 1024) | |
diskPath: @"ImageCache.db"]; | |
// Webview UI Cache | |
[baseCache registerCacheInclusionFilter:^BOOL(NSURLRequest *request) { | |
return [request.URL.host hasPrefix: [MBWebUIViewController webviewHost]]; | |
} lookup:^NSCachedURLResponse *(NSURLRequest *request) { | |
return [WebviewAssetCache cachedResponseForRequest:request]; | |
} storage:^(NSCachedURLResponse *response, NSURLRequest *request) { | |
[WebviewAssetCache storeCachedResponse:response forRequest:request]; | |
}]; | |
// Facebook Image Cache (caches the redirect to the fb image, while modifying what really gets stored) | |
NSRegularExpression *facebookRegex = [NSRegularExpression regularExpressionWithPattern:@"(graph.facebook.com/*/picture)+" | |
options:0 | |
error:&error]; | |
[baseCache registerCacheInclusionFilter:^BOOL(NSURLRequest *request) { | |
NSString *tmp; | |
NSRange fbRange = [facebookRegex rangeOfFirstMatchInString:(tmp = request.URL.absoluteString) options:0 range:NSMakeRange(0, tmp.length)]; | |
return fbRange.location != NSNotFound; | |
} lookup:^NSCachedURLResponse *(NSURLRequest *request) { | |
NSCachedURLResponse * cachedResponse = [ImageAssetCache cachedResponseForRequest:request]; | |
NSDate * dateSaved = cachedResponse.userInfo[kFBSURLCacheDateSavedKey]; | |
if (![dateSaved isToday]) { | |
dispatch_async(CONCURRENT_QUEUE, ^{ | |
NSURL * newURL = request.URL; | |
if ([newURL.absoluteString hasSuffix:@"/picture"]) { | |
// Lets falsify the facebook base URL, and instead fetch a 500x500 image :D | |
newURL = [NSURL URLWithString:[NSString stringWithFormat:@"%@?width=500&height=500",newURL.absoluteString]]; | |
AssetCacheLog(@"Faking the Facebook Profile Image Lookup %@",newURL.absoluteString); | |
} | |
// By using this request format, we skip the cache normally | |
NSURLRequest * cacheUpdateRequest = [NSURLRequest requestWithURL:newURL | |
cachePolicy:NSURLRequestReloadIgnoringLocalCacheData | |
timeoutInterval:30]; | |
NSError * error; | |
NSURLResponse * cacheUpdateResponse; | |
NSData * theData = [NSURLConnection sendSynchronousRequest: cacheUpdateRequest | |
returningResponse: &cacheUpdateResponse | |
error: &error]; | |
if (error){ | |
return; | |
} | |
NSCachedURLResponse * cacheable = [[NSCachedURLResponse alloc] initWithResponse: cacheUpdateResponse | |
data: theData | |
userInfo: @{ kFBSURLCacheDateSavedKey : [NSDate date] } | |
storagePolicy: NSURLCacheStorageAllowed]; | |
[ImageAssetCache storeCachedResponse:cacheable forRequest:request]; | |
}); | |
} | |
return cachedResponse; | |
} storage:^(NSCachedURLResponse *response, NSURLRequest *request) { | |
// Don't store this through the normal channels | |
// This lets us more easily falsify the redirect so the smaller points at the larger FB image :D | |
}]; | |
// Profile Image Cache | |
__block NSError * error; | |
NSRegularExpression *avatarRegex = [NSRegularExpression regularExpressionWithPattern:@"(/system/badges/icons/|/system/users/photos/|profile.*.fbcdn.net)+" | |
options:0 | |
error:&error]; | |
[baseCache registerCacheInclusionFilter:^BOOL(NSURLRequest *request) { | |
NSString *tmp; | |
NSRange avatarRange = [avatarRegex rangeOfFirstMatchInString:(tmp = request.URL.absoluteString) options:0 range:NSMakeRange(0, tmp.length)]; | |
return avatarRange.location != NSNotFound; | |
} lookup:^NSCachedURLResponse *(NSURLRequest *request) { | |
NSCachedURLResponse * cachedResponse = [ImageAssetCache cachedResponseForRequest:request]; | |
NSDate * dateSaved = cachedResponse.userInfo[kFBSURLCacheDateSavedKey]; | |
if (cachedResponse && ![dateSaved isToday]) { | |
// If we have a response in the cache, but it's not from today lets blindly update it :D | |
dispatch_async(CONCURRENT_QUEUE, ^{ | |
AssetCacheLog(@"Updating cache for %@",request.URL.absoluteString); | |
NSURLRequest * cacheUpdateRequest = [NSURLRequest requestWithURL:request.URL | |
cachePolicy:NSURLRequestReloadIgnoringLocalCacheData | |
timeoutInterval:30]; | |
NSError * error; | |
NSURLResponse * cacheUpdateResponse; | |
NSData * theData = [NSURLConnection sendSynchronousRequest: cacheUpdateRequest | |
returningResponse: &cacheUpdateResponse | |
error: &error]; | |
if (error){ | |
return; | |
} | |
NSCachedURLResponse * cacheable = [[NSCachedURLResponse alloc] initWithResponse: cacheUpdateResponse | |
data: theData | |
userInfo: @{ kFBSURLCacheDateSavedKey : [NSDate date] } | |
storagePolicy: NSURLCacheStorageAllowed]; | |
[ImageAssetCache storeCachedResponse:cacheable forRequest:request]; | |
}); | |
} | |
return cachedResponse; | |
} storage:^(NSCachedURLResponse *response, NSURLRequest *request) { | |
[ImageAssetCache storeCachedResponse:response forRequest:request]; | |
}]; | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment