NSURLRequest with caching not working

2019-04-16 17:44发布

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];
        }
    }];
}

3条回答
Viruses.
2楼-- · 2019-04-16 18:01

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.

查看更多
贪生不怕死
3楼-- · 2019-04-16 18:14

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
查看更多
手持菜刀,她持情操
4楼-- · 2019-04-16 18:20

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!)
查看更多
登录 后发表回答