77//
88
99#import " SDURLCache.h"
10+ #import " SDCachedURLResponse.h"
1011#import < CommonCrypto/CommonDigest.h>
12+ #import < UIKit/UIDevice.h>
13+
14+ // The removal of the NSCachedURLResponse category means that NSKeyedArchiver
15+ // will throw an EXC_BAD_ACCESS when attempting to load NSCachedURLResponse
16+ // data.
17+ // This means that this change requires a cache refresh, and a new cache key
18+ // namespace that will prevent this from happening.
19+ // Old cache keys will eventually be evicted from the system as new keys are
20+ // populated.
21+ static NSString *const kSDURLCacheVersion = @" V2" ;
1122
1223static NSTimeInterval const kSDURLCacheInfoDefaultMinCacheInterval = 5 * 60 ; // 5 minute
1324static NSString *const kSDURLCacheInfoFileName = @" cacheInfo.plist" ;
3041 return [dateFormatter autorelease ];
3142}
3243
33- @implementation NSCachedURLResponse (NSCoder )
34- #pragma clang diagnostic push
35- #pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"
36-
37- - (void )encodeWithCoder : (NSCoder *)coder
38- {
39- [coder encodeDataObject: self .data];
40- [coder encodeObject: self .response forKey: @" response" ];
41- [coder encodeObject: self .userInfo forKey: @" userInfo" ];
42- [coder encodeInt: self .storagePolicy forKey: @" storagePolicy" ];
43- }
44-
45- - (id )initWithCoder : (NSCoder *)coder
46- {
47- return [self initWithResponse: [coder decodeObjectForKey: @" response" ]
48- data: [coder decodeDataObject ]
49- userInfo: [coder decodeObjectForKey: @" userInfo" ]
50- storagePolicy: [coder decodeIntForKey: @" storagePolicy" ]];
51- }
52-
53- #pragma clang diagnostic pop
54-
55- @end
56-
57-
5844@interface SDURLCache ()
5945@property (nonatomic , retain ) NSString *diskCachePath;
6046@property (nonatomic , readonly ) NSMutableDictionary *diskCacheInfo;
@@ -87,8 +73,8 @@ + (NSString *)cacheKeyForURL:(NSURL *)url
8773 const char *str = [url.absoluteString UTF8String ];
8874 unsigned char r[CC_MD5_DIGEST_LENGTH];
8975 CC_MD5 (str, strlen (str), r);
90- return [NSString stringWithFormat: @" %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x " ,
91- r[0 ], r[1 ], r[2 ], r[3 ], r[4 ], r[5 ], r[6 ], r[7 ], r[8 ], r[9 ], r[10 ], r[11 ], r[12 ], r[13 ], r[14 ], r[15 ]];
76+ return [NSString stringWithFormat: @" %@ _ % 02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" ,
77+ kSDURLCacheVersion , r[0 ], r[1 ], r[2 ], r[3 ], r[4 ], r[5 ], r[6 ], r[7 ], r[8 ], r[9 ], r[10 ], r[11 ], r[12 ], r[13 ], r[14 ], r[15 ]];
9278}
9379
9480/*
@@ -368,7 +354,8 @@ - (void)balanceDiskUsage
368354- (void )storeToDisk : (NSDictionary *)context
369355{
370356 NSURLRequest *request = [context objectForKey: @" request" ];
371- NSCachedURLResponse *cachedResponse = [context objectForKey: @" cachedResponse" ];
357+ // use wrapper to ensure we save appropriate fields
358+ SDCachedURLResponse *cachedResponse = [SDCachedURLResponse cachedURLResponseWithNSCachedURLResponse: [context objectForKey: @" cachedResponse" ]];
372359
373360 NSString *cacheKey = [SDURLCache cacheKeyForURL: request.URL];
374361 NSString *cacheFilePath = [diskCachePath stringByAppendingPathComponent: cacheKey];
@@ -436,7 +423,12 @@ + (NSString *)defaultCachePath
436423
437424- (id )initWithMemoryCapacity : (NSUInteger )memoryCapacity diskCapacity : (NSUInteger )diskCapacity diskPath : (NSString *)path
438425{
439- if ((self = [super initWithMemoryCapacity: memoryCapacity diskCapacity: diskCapacity diskPath: path]))
426+ // iOS 5 implements disk caching. SDURLCache then disables itself at runtime if the current device OS
427+ // version is 5 or greater
428+ NSArray *version = [[UIDevice currentDevice ].systemVersion componentsSeparatedByString: @" ." ];
429+ disabled = [[version objectAtIndex: 0 ] intValue ] >= 5 ;
430+
431+ if ((self = [super initWithMemoryCapacity: memoryCapacity diskCapacity: diskCapacity diskPath: path]) && !disabled)
440432 {
441433 self.minCacheInterval = kSDURLCacheInfoDefaultMinCacheInterval ;
442434 self.diskCachePath = path;
@@ -455,6 +447,12 @@ - (id)initWithMemoryCapacity:(NSUInteger)memoryCapacity diskCapacity:(NSUInteger
455447
456448- (void )storeCachedResponse : (NSCachedURLResponse *)cachedResponse forRequest : (NSURLRequest *)request
457449{
450+ if (disabled)
451+ {
452+ [super storeCachedResponse: cachedResponse forRequest: request];
453+ return ;
454+ }
455+
458456 request = [SDURLCache canonicalRequestForRequest: request];
459457
460458 if (request.cachePolicy == NSURLRequestReloadIgnoringLocalCacheData
@@ -500,6 +498,8 @@ - (void)storeCachedResponse:(NSCachedURLResponse *)cachedResponse forRequest:(NS
500498
501499- (NSCachedURLResponse *)cachedResponseForRequest : (NSURLRequest *)request
502500{
501+ if (disabled) return [super cachedResponseForRequest: request];
502+
503503 request = [SDURLCache canonicalRequestForRequest: request];
504504
505505 NSCachedURLResponse *memoryResponse = [super cachedResponseForRequest: request];
@@ -517,7 +517,10 @@ - (NSCachedURLResponse *)cachedResponseForRequest:(NSURLRequest *)request
517517 NSMutableDictionary *accesses = [self .diskCacheInfo objectForKey: kSDURLCacheInfoAccessesKey ];
518518 if ([accesses objectForKey: cacheKey]) // OPTI: Check for cache-hit in a in-memory dictionary before hitting the file system
519519 {
520- NSCachedURLResponse *diskResponse = [NSKeyedUnarchiver unarchiveObjectWithFile: [diskCachePath stringByAppendingPathComponent: cacheKey]];
520+ // load wrapper
521+ SDCachedURLResponse *diskResponseWrapper = [NSKeyedUnarchiver unarchiveObjectWithFile: [diskCachePath stringByAppendingPathComponent: cacheKey]];
522+ NSCachedURLResponse *diskResponse = diskResponseWrapper.response ;
523+
521524 if (diskResponse)
522525 {
523526 // OPTI: Log the entry last access time for LRU cache eviction algorithm but don't save the dictionary
@@ -547,6 +550,8 @@ - (NSCachedURLResponse *)cachedResponseForRequest:(NSURLRequest *)request
547550
548551- (NSUInteger )currentDiskUsage
549552{
553+ if (disabled) return [super currentDiskUsage ];
554+
550555 if (!diskCacheInfo)
551556 {
552557 [self diskCacheInfo ];
@@ -556,6 +561,12 @@ - (NSUInteger)currentDiskUsage
556561
557562- (void )removeCachedResponseForRequest : (NSURLRequest *)request
558563{
564+ if (disabled)
565+ {
566+ [super removeCachedResponseForRequest: request];
567+ return ;
568+ }
569+
559570 request = [SDURLCache canonicalRequestForRequest: request];
560571
561572 [super removeCachedResponseForRequest: request];
@@ -567,6 +578,7 @@ - (void)removeAllCachedResponses
567578{
568579 [super removeAllCachedResponses ];
569580
581+ if (disabled) return ;
570582 NSFileManager *fileManager = [[NSFileManager alloc ] init ];
571583 [fileManager removeItemAtPath: diskCachePath error: NULL ];
572584 [fileManager release ];
@@ -586,7 +598,9 @@ - (BOOL)isCached:(NSURL *)url
586598 {
587599 return YES ;
588600 }
589-
601+
602+ if (disabled) return NO ;
603+
590604 NSString *cacheKey = [SDURLCache cacheKeyForURL: url];
591605 NSString *cacheFile = [diskCachePath stringByAppendingPathComponent: cacheKey];
592606 NSFileManager *manager = [[NSFileManager alloc ] init ];
@@ -605,6 +619,12 @@ - (BOOL)isCached:(NSURL *)url
605619
606620- (void )dealloc
607621{
622+ if (disabled)
623+ {
624+ [super dealloc ];
625+ return ;
626+ }
627+
608628 [periodicMaintenanceTimer invalidate ];
609629 [periodicMaintenanceTimer release ], periodicMaintenanceTimer = nil ;
610630 [periodicMaintenanceOperation release ], periodicMaintenanceOperation = nil ;
0 commit comments