More work on download cache
Added cache example to Mac project
Showing
7 changed files
with
159 additions
and
47 deletions
@@ -26,7 +26,7 @@ typedef enum _ASICacheStoragePolicy { | @@ -26,7 +26,7 @@ typedef enum _ASICacheStoragePolicy { | ||
26 | @protocol ASICacheDelegate <NSObject> | 26 | @protocol ASICacheDelegate <NSObject> |
27 | 27 | ||
28 | @required | 28 | @required |
29 | -- (BOOL)useDataFromCacheForRequest:(ASIHTTPRequest *)request; | 29 | +- (ASICachePolicy)defaultCachePolicy; |
30 | - (void)storeResponseForRequest:(ASIHTTPRequest *)request; | 30 | - (void)storeResponseForRequest:(ASIHTTPRequest *)request; |
31 | - (NSDictionary *)cachedHeadersForRequest:(ASIHTTPRequest *)request; | 31 | - (NSDictionary *)cachedHeadersForRequest:(ASIHTTPRequest *)request; |
32 | - (NSData *)cachedResponseDataForRequest:(ASIHTTPRequest *)request; | 32 | - (NSData *)cachedResponseDataForRequest:(ASIHTTPRequest *)request; |
@@ -13,7 +13,7 @@ | @@ -13,7 +13,7 @@ | ||
13 | ASICachePolicy defaultCachePolicy; | 13 | ASICachePolicy defaultCachePolicy; |
14 | ASICacheStoragePolicy defaultCacheStoragePolicy; | 14 | ASICacheStoragePolicy defaultCacheStoragePolicy; |
15 | NSString *storagePath; | 15 | NSString *storagePath; |
16 | - NSLock *accessLock; | 16 | + NSRecursiveLock *accessLock; |
17 | BOOL shouldRespectCacheHeaders; | 17 | BOOL shouldRespectCacheHeaders; |
18 | } | 18 | } |
19 | + (id)sharedCache; | 19 | + (id)sharedCache; |
@@ -22,6 +22,6 @@ | @@ -22,6 +22,6 @@ | ||
22 | @property (assign) ASICachePolicy defaultCachePolicy; | 22 | @property (assign) ASICachePolicy defaultCachePolicy; |
23 | @property (assign) ASICacheStoragePolicy defaultCacheStoragePolicy; | 23 | @property (assign) ASICacheStoragePolicy defaultCacheStoragePolicy; |
24 | @property (retain) NSString *storagePath; | 24 | @property (retain) NSString *storagePath; |
25 | -@property (retain) NSLock *accessLock; | 25 | +@property (retain) NSRecursiveLock *accessLock; |
26 | @property (assign) BOOL shouldRespectCacheHeaders; | 26 | @property (assign) BOOL shouldRespectCacheHeaders; |
27 | @end | 27 | @end |
@@ -27,7 +27,7 @@ static NSString *permanentCacheFolder = @"PermanentStore"; | @@ -27,7 +27,7 @@ static NSString *permanentCacheFolder = @"PermanentStore"; | ||
27 | self = [super init]; | 27 | self = [super init]; |
28 | [self setDefaultCachePolicy:ASIReloadIfDifferentCachePolicy]; | 28 | [self setDefaultCachePolicy:ASIReloadIfDifferentCachePolicy]; |
29 | [self setDefaultCacheStoragePolicy:ASICacheForSessionDurationCacheStoragePolicy]; | 29 | [self setDefaultCacheStoragePolicy:ASICacheForSessionDurationCacheStoragePolicy]; |
30 | - [self setAccessLock:[[[NSLock alloc] init] autorelease]]; | 30 | + [self setAccessLock:[[[NSRecursiveLock alloc] init] autorelease]]; |
31 | return self; | 31 | return self; |
32 | } | 32 | } |
33 | 33 | ||
@@ -51,21 +51,23 @@ static NSString *permanentCacheFolder = @"PermanentStore"; | @@ -51,21 +51,23 @@ static NSString *permanentCacheFolder = @"PermanentStore"; | ||
51 | - (void)setStoragePath:(NSString *)path | 51 | - (void)setStoragePath:(NSString *)path |
52 | { | 52 | { |
53 | [[self accessLock] lock]; | 53 | [[self accessLock] lock]; |
54 | + [self clearCachedResponsesForStoragePolicy:ASICacheForSessionDurationCacheStoragePolicy]; | ||
54 | [storagePath release]; | 55 | [storagePath release]; |
55 | storagePath = [path retain]; | 56 | storagePath = [path retain]; |
56 | BOOL isDirectory = NO; | 57 | BOOL isDirectory = NO; |
57 | NSArray *directories = [NSArray arrayWithObjects:path,[path stringByAppendingPathComponent:sessionCacheFolder],[path stringByAppendingPathComponent:permanentCacheFolder],nil]; | 58 | NSArray *directories = [NSArray arrayWithObjects:path,[path stringByAppendingPathComponent:sessionCacheFolder],[path stringByAppendingPathComponent:permanentCacheFolder],nil]; |
58 | for (NSString *directory in directories) { | 59 | for (NSString *directory in directories) { |
59 | - BOOL exists = [[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:&isDirectory]; | 60 | + BOOL exists = [[NSFileManager defaultManager] fileExistsAtPath:directory isDirectory:&isDirectory]; |
60 | if (exists && !isDirectory) { | 61 | if (exists && !isDirectory) { |
61 | - [NSException raise:@"FileExistsAtCachePath" format:@"Cannot create a directory for the cache at '%@', because a file already exists",path]; | 62 | + [NSException raise:@"FileExistsAtCachePath" format:@"Cannot create a directory for the cache at '%@', because a file already exists",directory]; |
62 | } else if (!exists) { | 63 | } else if (!exists) { |
63 | - [[NSFileManager defaultManager] createDirectoryAtPath:path attributes:nil]; | 64 | + [[NSFileManager defaultManager] createDirectoryAtPath:directory attributes:nil]; |
64 | - if (![[NSFileManager defaultManager] fileExistsAtPath:path]) { | 65 | + if (![[NSFileManager defaultManager] fileExistsAtPath:directory]) { |
65 | - [NSException raise:@"FailedToCreateCacheDirectory" format:@"Failed to create a directory for the cache at '%@'",path]; | 66 | + [NSException raise:@"FailedToCreateCacheDirectory" format:@"Failed to create a directory for the cache at '%@'",directory]; |
66 | } | 67 | } |
67 | } | 68 | } |
68 | } | 69 | } |
70 | + [self clearCachedResponsesForStoragePolicy:ASICacheForSessionDurationCacheStoragePolicy]; | ||
69 | [[self accessLock] unlock]; | 71 | [[self accessLock] unlock]; |
70 | } | 72 | } |
71 | 73 | ||
@@ -103,10 +105,14 @@ static NSString *permanentCacheFolder = @"PermanentStore"; | @@ -103,10 +105,14 @@ static NSString *permanentCacheFolder = @"PermanentStore"; | ||
103 | NSString *metadataPath = [path stringByAppendingPathExtension:@"cachedheaders"]; | 105 | NSString *metadataPath = [path stringByAppendingPathExtension:@"cachedheaders"]; |
104 | NSString *dataPath = [path stringByAppendingPathExtension:@"cacheddata"]; | 106 | NSString *dataPath = [path stringByAppendingPathExtension:@"cacheddata"]; |
105 | 107 | ||
106 | - [[request responseHeaders] writeToFile:metadataPath atomically:NO]; | 108 | + NSMutableDictionary *responseHeaders = [NSMutableDictionary dictionaryWithDictionary:[request responseHeaders]]; |
109 | + if ([request isResponseCompressed]) { | ||
110 | + [responseHeaders removeObjectForKey:@"Content-Encoding"]; | ||
111 | + } | ||
112 | + [responseHeaders writeToFile:metadataPath atomically:NO]; | ||
107 | 113 | ||
108 | if ([request responseData]) { | 114 | if ([request responseData]) { |
109 | - [[request responseData] writeToFile:path atomically:NO]; | 115 | + [[request responseData] writeToFile:dataPath atomically:NO]; |
110 | } else if ([request downloadDestinationPath]) { | 116 | } else if ([request downloadDestinationPath]) { |
111 | [[NSFileManager defaultManager] copyPath:[request downloadDestinationPath] toPath:dataPath handler:nil]; | 117 | [[NSFileManager defaultManager] copyPath:[request downloadDestinationPath] toPath:dataPath handler:nil]; |
112 | } | 118 | } |
@@ -185,27 +191,6 @@ static NSString *permanentCacheFolder = @"PermanentStore"; | @@ -185,27 +191,6 @@ static NSString *permanentCacheFolder = @"PermanentStore"; | ||
185 | return YES; | 191 | return YES; |
186 | } | 192 | } |
187 | 193 | ||
188 | -- (BOOL)useDataFromCacheForRequest:(ASIHTTPRequest *)request | ||
189 | -{ | ||
190 | - if (![self storagePath]) { | ||
191 | - return NO; | ||
192 | - } | ||
193 | - NSDictionary *headers = [self cachedHeadersForRequest:request]; | ||
194 | - if (!headers) { | ||
195 | - return NO; | ||
196 | - } | ||
197 | - NSString *dataPath = [self pathToCachedResponseDataForRequest:request]; | ||
198 | - if (!dataPath) { | ||
199 | - return NO; | ||
200 | - } | ||
201 | - [request setResponseHeaders:headers]; | ||
202 | - if ([request downloadDestinationPath]) { | ||
203 | - [request setDownloadDestinationPath:dataPath]; | ||
204 | - } else { | ||
205 | - [request setRawResponseData:[NSMutableData dataWithData:[self cachedResponseDataForRequest:request]]]; | ||
206 | - } | ||
207 | - return YES; | ||
208 | -} | ||
209 | 194 | ||
210 | - (void)setDefaultCachePolicy:(ASICachePolicy)cachePolicy | 195 | - (void)setDefaultCachePolicy:(ASICachePolicy)cachePolicy |
211 | { | 196 | { |
@@ -23,7 +23,7 @@ | @@ -23,7 +23,7 @@ | ||
23 | 23 | ||
24 | 24 | ||
25 | // Automatically set on build | 25 | // Automatically set on build |
26 | -NSString *ASIHTTPRequestVersion = @"v1.6.2-9 2010-05-02"; | 26 | +NSString *ASIHTTPRequestVersion = @"v1.6.2-10 2010-05-02"; |
27 | 27 | ||
28 | NSString* const NetworkRequestErrorDomain = @"ASIHTTPRequestErrorDomain"; | 28 | NSString* const NetworkRequestErrorDomain = @"ASIHTTPRequestErrorDomain"; |
29 | 29 | ||
@@ -145,6 +145,8 @@ static id <ASICacheDelegate> defaultCache = nil; | @@ -145,6 +145,8 @@ static id <ASICacheDelegate> defaultCache = nil; | ||
145 | 145 | ||
146 | - (void)updateStatus:(NSTimer*)timer; | 146 | - (void)updateStatus:(NSTimer*)timer; |
147 | 147 | ||
148 | +- (BOOL)useDataFromCache; | ||
149 | + | ||
148 | #if TARGET_OS_IPHONE | 150 | #if TARGET_OS_IPHONE |
149 | + (void)registerForNetworkReachabilityNotifications; | 151 | + (void)registerForNetworkReachabilityNotifications; |
150 | + (void)unsubscribeFromNetworkReachabilityNotifications; | 152 | + (void)unsubscribeFromNetworkReachabilityNotifications; |
@@ -798,15 +800,20 @@ static id <ASICacheDelegate> defaultCache = nil; | @@ -798,15 +800,20 @@ static id <ASICacheDelegate> defaultCache = nil; | ||
798 | return; | 800 | return; |
799 | } | 801 | } |
800 | 802 | ||
801 | - // See if we should pull from the cache rather than fetching the data | 803 | + if ([self downloadCache]) { |
802 | - if ([self downloadCache] && [self cachePolicy] == ASIOnlyLoadIfNotCachedCachePolicy) { | 804 | + if ([self cachePolicy] == ASIDefaultCachePolicy) { |
803 | - if ([[self downloadCache] useDataFromCacheForRequest:self]) { | 805 | + [self setCachePolicy:[[self downloadCache] defaultCachePolicy]]; |
804 | - [[self cancelledLock] unlock]; | 806 | + } |
805 | - return; | 807 | + |
808 | + // See if we should pull from the cache rather than fetching the data | ||
809 | + if ([self cachePolicy] == ASIOnlyLoadIfNotCachedCachePolicy) { | ||
810 | + if ([self useDataFromCache]) { | ||
811 | + [[self cancelledLock] unlock]; | ||
812 | + return; | ||
813 | + } | ||
806 | } | 814 | } |
807 | } | 815 | } |
808 | 816 | ||
809 | - | ||
810 | [self requestStarted]; | 817 | [self requestStarted]; |
811 | 818 | ||
812 | [self setDownloadComplete:NO]; | 819 | [self setDownloadComplete:NO]; |
@@ -1573,11 +1580,7 @@ static id <ASICacheDelegate> defaultCache = nil; | @@ -1573,11 +1580,7 @@ static id <ASICacheDelegate> defaultCache = nil; | ||
1573 | } | 1580 | } |
1574 | 1581 | ||
1575 | if ([self downloadCache] && [self cachePolicy] == ASIUseCacheIfLoadFailsCachePolicy) { | 1582 | if ([self downloadCache] && [self cachePolicy] == ASIUseCacheIfLoadFailsCachePolicy) { |
1576 | - if ([[self downloadCache] useDataFromCacheForRequest:self]) { | 1583 | + if ([self useDataFromCache]) { |
1577 | - [self markAsFinished]; | ||
1578 | - if ([self mainRequest]) { | ||
1579 | - [[self mainRequest] markAsFinished]; | ||
1580 | - } | ||
1581 | return; | 1584 | return; |
1582 | } | 1585 | } |
1583 | } | 1586 | } |
@@ -1638,10 +1641,8 @@ static id <ASICacheDelegate> defaultCache = nil; | @@ -1638,10 +1641,8 @@ static id <ASICacheDelegate> defaultCache = nil; | ||
1638 | CFRelease(headerFields); | 1641 | CFRelease(headerFields); |
1639 | 1642 | ||
1640 | if ([self downloadCache] && [self cachePolicy] == ASIReloadIfDifferentCachePolicy) { | 1643 | if ([self downloadCache] && [self cachePolicy] == ASIReloadIfDifferentCachePolicy) { |
1641 | - if ([[self downloadCache] useDataFromCacheForRequest:self]) { | 1644 | + if ([self useDataFromCache]) { |
1642 | CFRelease(message); | 1645 | CFRelease(message); |
1643 | - [self cancelLoad]; | ||
1644 | - [self markAsFinished]; | ||
1645 | return; | 1646 | return; |
1646 | } | 1647 | } |
1647 | } | 1648 | } |
@@ -2662,6 +2663,45 @@ static id <ASICacheDelegate> defaultCache = nil; | @@ -2662,6 +2663,45 @@ static id <ASICacheDelegate> defaultCache = nil; | ||
2662 | CFRunLoopStop(CFRunLoopGetCurrent()); | 2663 | CFRunLoopStop(CFRunLoopGetCurrent()); |
2663 | } | 2664 | } |
2664 | 2665 | ||
2666 | +- (BOOL)useDataFromCache | ||
2667 | +{ | ||
2668 | + NSDictionary *headers = [[self downloadCache] cachedHeadersForRequest:self]; | ||
2669 | + if (!headers) { | ||
2670 | + return NO; | ||
2671 | + } | ||
2672 | + NSString *dataPath = [[self downloadCache] pathToCachedResponseDataForRequest:self]; | ||
2673 | + if (!dataPath) { | ||
2674 | + return NO; | ||
2675 | + } | ||
2676 | + | ||
2677 | + [self cancelLoad]; | ||
2678 | + | ||
2679 | + ASIHTTPRequest *theRequest = self; | ||
2680 | + if ([self mainRequest]) { | ||
2681 | + theRequest = [self mainRequest]; | ||
2682 | + } | ||
2683 | + [theRequest setResponseHeaders:headers]; | ||
2684 | + if ([theRequest downloadDestinationPath]) { | ||
2685 | + [theRequest setDownloadDestinationPath:dataPath]; | ||
2686 | + } else { | ||
2687 | + [theRequest setRawResponseData:[NSMutableData dataWithData:[[self downloadCache] cachedResponseDataForRequest:self]]]; | ||
2688 | + } | ||
2689 | + [theRequest setContentLength:[[[self responseHeaders] objectForKey:@"Content-Length"] longLongValue]]; | ||
2690 | + [theRequest setTotalBytesRead:[self contentLength]]; | ||
2691 | + | ||
2692 | + | ||
2693 | + [theRequest setComplete:YES]; | ||
2694 | + [theRequest setDownloadComplete:YES]; | ||
2695 | + | ||
2696 | + [theRequest updateProgressIndicators]; | ||
2697 | + [theRequest requestFinished]; | ||
2698 | + [theRequest markAsFinished]; | ||
2699 | + if ([self mainRequest]) { | ||
2700 | + [self markAsFinished]; | ||
2701 | + } | ||
2702 | + return YES; | ||
2703 | +} | ||
2704 | + | ||
2665 | - (BOOL)retryUsingNewConnection | 2705 | - (BOOL)retryUsingNewConnection |
2666 | { | 2706 | { |
2667 | if ([self retryCount] == 0) { | 2707 | if ([self retryCount] == 0) { |
@@ -40,6 +40,11 @@ | @@ -40,6 +40,11 @@ | ||
40 | 40 | ||
41 | ASIHTTPRequest *bigFetchRequest; | 41 | ASIHTTPRequest *bigFetchRequest; |
42 | IBOutlet NSTextField *postStatus; | 42 | IBOutlet NSTextField *postStatus; |
43 | + | ||
44 | + IBOutlet NSTableView *tableView; | ||
45 | + IBOutlet NSTextField *tableLoadStatus; | ||
46 | + NSMutableArray *rowData; | ||
47 | + ASINetworkQueue *tableQueue; | ||
43 | } | 48 | } |
44 | 49 | ||
45 | - (IBAction)simpleURLFetch:(id)sender; | 50 | - (IBAction)simpleURLFetch:(id)sender; |
@@ -57,6 +62,10 @@ | @@ -57,6 +62,10 @@ | ||
57 | 62 | ||
58 | - (IBAction)throttleBandwidth:(id)sender; | 63 | - (IBAction)throttleBandwidth:(id)sender; |
59 | 64 | ||
65 | +- (IBAction)reloadTableData:(id)sender; | ||
66 | +- (IBAction)clearCache:(id)sender; | ||
60 | 67 | ||
61 | @property (retain, nonatomic) ASIHTTPRequest *bigFetchRequest; | 68 | @property (retain, nonatomic) ASIHTTPRequest *bigFetchRequest; |
69 | +@property (retain, nonatomic) NSMutableArray *rowData; | ||
70 | +@property (retain, nonatomic) ASINetworkQueue *tableQueue; | ||
62 | @end | 71 | @end |
@@ -9,6 +9,7 @@ | @@ -9,6 +9,7 @@ | ||
9 | #import "ASIHTTPRequest.h" | 9 | #import "ASIHTTPRequest.h" |
10 | #import "ASIFormDataRequest.h" | 10 | #import "ASIFormDataRequest.h" |
11 | #import "ASINetworkQueue.h" | 11 | #import "ASINetworkQueue.h" |
12 | +#import "ASIDownloadCache.h" | ||
12 | 13 | ||
13 | @interface AppDelegate () | 14 | @interface AppDelegate () |
14 | - (void)updateBandwidthUsageIndicator; | 15 | - (void)updateBandwidthUsageIndicator; |
@@ -25,6 +26,7 @@ | @@ -25,6 +26,7 @@ | ||
25 | 26 | ||
26 | @implementation AppDelegate | 27 | @implementation AppDelegate |
27 | 28 | ||
29 | + | ||
28 | - (id)init | 30 | - (id)init |
29 | { | 31 | { |
30 | [super init]; | 32 | [super init]; |
@@ -307,6 +309,82 @@ | @@ -307,6 +309,82 @@ | ||
307 | [postStatus setStringValue:[NSString stringWithFormat:@"Post Failed: %@",[[request error] localizedDescription]]]; | 309 | [postStatus setStringValue:[NSString stringWithFormat:@"Post Failed: %@",[[request error] localizedDescription]]]; |
308 | } | 310 | } |
309 | 311 | ||
312 | +- (void)tabView:(NSTabView *)tabView didSelectTabViewItem:(NSTabViewItem *)tabViewItem | ||
313 | +{ | ||
314 | + if ([[tabViewItem label] isEqualToString:@"Cache"]) { | ||
315 | + [self reloadTableData:nil]; | ||
316 | + } | ||
317 | +} | ||
318 | + | ||
319 | +- (IBAction)reloadTableData:(id)sender | ||
320 | +{ | ||
321 | + [[self tableQueue] cancelAllOperations]; | ||
322 | + [self setTableQueue:[ASINetworkQueue queue]]; | ||
323 | + [[ASIDownloadCache sharedCache] setDefaultCachePolicy:ASIOnlyLoadIfNotCachedCachePolicy]; | ||
324 | + | ||
325 | + ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/table-row-data.xml"]]; | ||
326 | + [request setDownloadCache:[ASIDownloadCache sharedCache]]; | ||
327 | + [request setDidFinishSelector:@selector(tableViewDataFetchFinished:)]; | ||
328 | + [request setDelegate:self]; | ||
329 | + [[self tableQueue] addOperation:request]; | ||
330 | + [[self tableQueue] go]; | ||
331 | +} | ||
332 | + | ||
333 | +- (void)tableViewDataFetchFailed:(ASIHTTPRequest *)request | ||
334 | +{ | ||
335 | + if ([[request error] domain] != NetworkRequestErrorDomain || ![[request error] code] == ASIRequestCancelledErrorType) { | ||
336 | + [tableLoadStatus setStringValue:@"Loading data failed"]; | ||
337 | + } | ||
338 | +} | ||
339 | + | ||
340 | +- (void)tableViewDataFetchFinished:(ASIHTTPRequest *)request | ||
341 | +{ | ||
342 | + [self setRowData:[NSMutableArray array]]; | ||
343 | + NSXMLDocument *xml = [[[NSXMLDocument alloc] initWithData:[request responseData] options:NSXMLDocumentValidate error:nil] autorelease]; | ||
344 | + for (NSXMLElement *row in [[xml rootElement] elementsForName:@"row"]) { | ||
345 | + NSMutableDictionary *rowInfo = [NSMutableDictionary dictionary]; | ||
346 | + NSString *description = [[[row elementsForName:@"description"] objectAtIndex:0] stringValue]; | ||
347 | + [rowInfo setValue:description forKey:@"description"]; | ||
348 | + NSString *imageURL = [[[row elementsForName:@"image"] objectAtIndex:0] stringValue]; | ||
349 | + ASIHTTPRequest *imageRequest = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:imageURL]]; | ||
350 | + [imageRequest setDownloadCache:[ASIDownloadCache sharedCache]]; | ||
351 | + [imageRequest setDidFinishSelector:@selector(rowImageDownloadFinished:)]; | ||
352 | + [imageRequest setDidFailSelector:@selector(tableViewDataFetchFailed:)]; | ||
353 | + [imageRequest setDelegate:self]; | ||
354 | + [imageRequest setUserInfo:rowInfo]; | ||
355 | + [[self tableQueue] addOperation:imageRequest]; | ||
356 | + [[self rowData] addObject:rowInfo]; | ||
357 | + } | ||
358 | + [tableView reloadData]; | ||
359 | +} | ||
360 | + | ||
361 | +- (NSInteger)numberOfRowsInTableView:(NSTableView *)aTableView | ||
362 | +{ | ||
363 | + return [[self rowData] count]; | ||
364 | +} | ||
365 | + | ||
366 | +- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex | ||
367 | +{ | ||
368 | + if ([[aTableColumn identifier] isEqualToString:@"image"]) { | ||
369 | + return [[[self rowData] objectAtIndex:rowIndex] objectForKey:@"image"]; | ||
370 | + } else { | ||
371 | + return [[[self rowData] objectAtIndex:rowIndex] objectForKey:@"description"]; | ||
372 | + } | ||
373 | +} | ||
374 | + | ||
375 | +- (void)rowImageDownloadFinished:(ASIHTTPRequest *)request | ||
376 | +{ | ||
377 | + [(NSMutableDictionary *)[request userInfo] setObject:[[[NSImage alloc] initWithData:[request responseData]] autorelease] forKey:@"image"]; | ||
378 | + [tableView reloadData]; // Not efficient, but I hate table view programming :) | ||
379 | +} | ||
380 | + | ||
381 | +- (IBAction)clearCache:(id)sender | ||
382 | +{ | ||
383 | + [[ASIDownloadCache sharedCache] clearCachedResponsesForStoragePolicy:ASICacheForSessionDurationCacheStoragePolicy]; | ||
384 | +} | ||
385 | + | ||
310 | 386 | ||
311 | @synthesize bigFetchRequest; | 387 | @synthesize bigFetchRequest; |
388 | +@synthesize rowData; | ||
389 | +@synthesize tableQueue; | ||
312 | @end | 390 | @end |
This diff is collapsed. Click to expand it.
-
Please register or login to post a comment