Skip to content

Instantly share code, notes, and snippets.

@fbartho
Last active December 15, 2015 19:58
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 fbartho/5314747 to your computer and use it in GitHub Desktop.
Save fbartho/5314747 to your computer and use it in GitHub Desktop.
Example integration of FBStackableURLCache
// 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