Skip to content

Instantly share code, notes, and snippets.

@Goos
Last active October 2, 2018 19:31
Show Gist options
  • Save Goos/23184727755eb9eee494 to your computer and use it in GitHub Desktop.
Save Goos/23184727755eb9eee494 to your computer and use it in GitHub Desktop.
An NSURLCache subclass supporting block-based filters.
#import <Foundation/Foundation.h>
@interface GOFilteringURLCache : NSURLCache
- (void)addFilterForURL:(NSURL *)URL response:(NSCachedURLResponse *(^)(NSURLRequest *request))responseBlock;
- (void)removeFiltersForURL:(NSURL *)URL;
@end
#import "GOFilteringURLCache.h"
@interface GOURLFilter : NSObject
@property (copy, nonatomic) NSURL *targetURL;
@property (copy, nonatomic) NSCachedURLResponse *(^responseBlock)(NSURLRequest *request);
- (instancetype)initWithTargetURL:(NSURL *)targetURL response:(NSCachedURLResponse *(^)(NSURLRequest *request))responseBlock;
@end
@implementation GOURLFilter
- (instancetype)initWithTargetURL:(NSURL *)targetURL response:(NSCachedURLResponse *(^)(NSURLRequest *request))responseBlock
{
self = [super init];
if (!self) {
return nil;
}
_targetURL = targetURL;
_responseBlock = responseBlock;
return self;
}
- (NSCachedURLResponse *)triggerWithRequest:(NSURLRequest *)request
{
NSCachedURLResponse *response = nil;
if (self.responseBlock) {
response = self.responseBlock(request);
}
return response;
}
@end
@interface GOFilteringURLCache ()
@property (strong, nonatomic) NSMutableArray *filters;
@end
@implementation GOFilteringURLCache
- (instancetype)initWithMemoryCapacity:(NSUInteger)memoryCapacity diskCapacity:(NSUInteger)diskCapacity diskPath:(NSString *)path
{
self = [super initWithMemoryCapacity:memoryCapacity diskCapacity:diskCapacity diskPath:path];
if (!self) {
return nil;
}
_filters = [NSMutableArray array];
return self;
}
- (void)addFilterForURL:(NSURL *)URL response:(NSCachedURLResponse *(^)(NSURLRequest *request))responseBlock
{
if (!URL || !responseBlock) {
return;
}
GOURLFilter *filter = [[GOURLFilter alloc] initWithTargetURL:URL response:responseBlock];
[self.filters addObject:filter];
}
- (void)removeFiltersForURL:(NSURL *)URL
{
NSArray *matchingFilters = [self.filters arrayByFilteringWithBlock:^BOOL(GOURLFilter *filter, NSUInteger idx) {
return [filter.targetURL isEqual:URL];
}];
[self.filters removeObjectsInArray:matchingFilters];
}
- (NSCachedURLResponse *)cachedResponseForRequest:(NSURLRequest *)request
{
NSString *URLString = request.URL.absoluteString;
// See if we have any matching filters
GOURLFilter *matchingFilter = [self.filters arrayByFilteringWithBlock:^BOOL(GOURLFilter *filter, NSUInteger idx) {
return [filter.targetURL.absoluteString isEqual:URLString];
}].firstObject;
NSCachedURLResponse *response = nil;
if (matchingFilter) {
response = [matchingFilter triggerWithRequest:request];
}
if (response == nil) {
response = [super cachedResponseForRequest:request];
}
return response;
}
@end
NSURL *filteredURL = [NSURL URLWithString:@"http://example.com"];
[((GOFilteringURLCache *)[NSURLCache sharedURLCache]) addFilterForURL:filteredURL response:^NSCachedURLResponse *(NSURLRequest *request) {
// Creating a mocked response for the request with an empty body.
NSURLResponse *response = [[NSURLResponse alloc] initWithURL:filteredURL MIMEType:kPlainTextMIMEType expectedContentLength:1 textEncodingName:nil];
NSCachedURLResponse *cachedResponse = [[NSCachedURLResponse alloc] initWithResponse:response data:[NSData dataWithBytes:" " length:1]];
return cachedResponse;
}];
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment