I am trying to cache my nsurlrequest data. Prior to this i was successfully downloading data from the server, ever since I tried to implement this cache its been making my application fall over. Im hoping someone can look at the code i have so far and help me to get it workig.. I think I have roughly 95% of it done.
- (IBAction)setRequestString:(NSString *)string
{
//Set database address
NSMutableString *databaseURL = [[NSMutableString alloc] initWithString:@"http://127.0.0.1:29/"]; // imac development
//PHP file name is being set from the parent view
[databaseURL appendString:string];
//call ASIHTTP delegates (Used to connect to database)
NSURL *url = [NSURL URLWithString:databaseURL];
//SynchronousRequest to grab the data, also setting up the cachePolicy
NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:60.0]; //if request dose not finish happen within 60 second timeout.
//This nsdata will be used to put the cache into
NSData *cacheData = [[NSData alloc] init];
//Create my own NSCachedURLResponse and add it to the cache
NSURLResponse *responseToCache = [[NSURLResponse alloc] initWithURL:url MIMEType:@"text/xml" expectedContentLength:[cacheData length] textEncodingName:nil];
//Set up the cache
NSCachedURLResponse *cacheResponse = [[NSCachedURLResponse alloc] initWithResponse:responseToCache data:cacheData];
[[NSURLCache sharedURLCache] storeCachedResponse:cacheResponse forRequest:request];
//check if its really there
NSLog(@"cache = %@", [[NSURLCache sharedURLCache] cachedResponseForRequest:request]);
//If no cache do this stuff, connect to the db and perform these actions. I think this is what i am supposed to be doing.
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
{
if ([data length] > 0 && error == nil){
[self receivedData:data];
}else if ([data length] == 0 && error == nil){
[self emptyReply];
}else if (error != nil && error.code == NSURLErrorTimedOut){
[self timedOut];
}else if (error != nil){
[self downloadError:error];
}
}];
}
Follow this link for an dead simple way of doing this using a category method on NSURLConnection. It's for asynchronous requests but can be adapted easily for synchronous ones.
Also I strongly advise that you use a private property or instance variable for your NSOperationQueue so that all your requests use the same operation queue.
Thanks for the code, I managed to get it working with your example.
The cacheData is the data to be cached, not where it is cached in.
And you have to get and handle the cache yourself.
I give you a little example for clarity:
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:requestUrl cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
NSCachedURLResponse *cachedURLResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:request];
NSData *responseData;
//check if has cache
if(cachedURLResponse && cachedURLResponse != (id)[NSNull null])
{
responseData = [cachedURLResponse data];
}
else //if no cache get it from the server.
{
__autoreleasing NSError *error = nil;
NSHTTPURLResponse *response = nil;
responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
//..handle response and error
//cache received data
cachedURLResponse = [[NSCachedURLResponse alloc] initWithResponse:response data:responseData userInfo:nil storagePolicy:NSURLCacheStorageAllowed];
//store in cache
[[NSURLCache sharedURLCache] storeCachedResponse:cachedURLResponse forRequest:request];
}
//..handle responseData
Swift:
let isReachable = NetworkManager.sharedManager().isInternetReachable()//Reachability- to check internet is available
let urlRequestCache:NSURLRequest!
if isReachable != 0 { //If ther is intenet then load and caching it
urlRequestCache = NSURLRequest(URL: NSURL(string: url)!, cachePolicy: NSURLRequestCachePolicy.UseProtocolCachePolicy, timeoutInterval: 10)
let session = NSURLSession.sharedSession()
session.dataTaskWithRequest(urlRequestCache, completionHandler: {(data, response, error) in
let newCachedResponse = NSCachedURLResponse(response:(response)!, data:(data)!, userInfo:nil, storagePolicy: .Allowed)
NSURLCache.sharedURLCache().storeCachedResponse(newCachedResponse, forRequest:urlRequestCache)
}).resume()
}else{ // check the cache is available
urlRequestCache = NSURLRequest(URL: NSURL(string: url)!, cachePolicy: NSURLRequestCachePolicy.ReturnCacheDataElseLoad, timeoutInterval: 60)
guard let _ = NSURLCache.sharedURLCache().cachedResponseForRequest(urlRequestCache) else{ //checking cache if false then
print(" cache not found:)")
return
}
print(" cache found:)")
}
browserView?.loadRequest(urlRequestCache!)