How to enable caching in UIWebView? - ios

how I can enable caching in an UIWebView?
It's frustrating. I'm looking for hours but no mentioned solutions in many other posts doesn't helped me.
I tried many solutions like https://stackoverflow.com/a/26174438, https://stackoverflow.com/a/1424301, http://codewithchris.com/tutorial-how-to-use-ios-nsurlconnection-by-example/, https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/URLLoadingSystem/Concepts/CachePolicies.html, iOS Cache a UIWebView, etc.
My code looks like
[self setUrl:[[NSString alloc] initWithFormat:#"http://example.com"]];
[[NSURLCache sharedURLCache] setDiskCapacity:0];
[[NSURLCache sharedURLCache] setMemoryCapacity:0];
[self setLoadUrl: [NSURL URLWithString:[self url]]];
[self setRequestObj:[NSURLRequest requestWithURL:[self loadUrl]]];
if cachingis disabled. If it's turned on I have
if([[self cache] isEqualToNumber:[[NSNumber alloc] initWithInt:1]])
{
[[NSURLCache sharedURLCache] setDiskCapacity:4 * 1024 * 1024];
[[NSURLCache sharedURLCache] setMemoryCapacity:32 * 1024 * 1024];
[self setRequestObj:[NSURLRequest requestWithURL:loadUrl cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0]];
}
How

#Premox I think you can choose a different way. After your uiwebview loaded page you can get a response html convert to NSString class and save it to cache or serialize as you wanna

Related

Can't disable UIWebView caching

I'm making a series of requests with UIWebView and I need to keep UIWebView's cache clear so that I could start each new request from scratch. So before performing every request I'm doing the following:
[[NSURLCache sharedURLCache] removeAllCachedResponses];
[[NSURLCache sharedURLCache] setDiskCapacity:0];
[[NSURLCache sharedURLCache] setMemoryCapacity:0];
But unfortunately it doesn't help. Every time the first request takes approximately 4 seconds while every following request about 1.5 seconds, so obviously the loaded data is being cached somewhere.
I also tried set caching policy for the request explicitly, like this:
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:URL];
request.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
[self.webView loadRequest:request];
but it doesn't help as well. The very first request takes significantly longer time than the following ones. Just like without setting caching policy for the request at all.
Any ideas, guys?
Try this code:
NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
for (NSHTTPCookie *each in cookieStorage.cookies)
{
[cookieStorage deleteCookie:each];
}
Try using NSURLCacheStorageNotAllowed. This specifies that storage in NSURLCache is not allowed in any fashion, either in memory or on disk.
↳ Foundation Framework Reference > NSCachedURLResponse Class Reference

NSURLConnection is growing in instruments, is this NSURLCache?

So I have a memory problem with my app. The app has a MKMapView with MKOverlayRenderer which loads images on the map. Everything working ok but after 30-60 minutes the app crashes due memory.
With Instruments I found that NSURLConnection is growing and because I cannot find anything else (besides all kind of stuff I dont understand) I think thats is my problem.
Screenshot instruments after runnning for 1-2 minutes:
Screenshot instruments after running for 12-13 minutes:
Images are loaded like this in the canDrawMapRect method and saved to tmp folder (if I turn this off the NSURLConnection won't grow that high):
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];
[NSURLConnection sendAsynchronousRequest:request
queue:[OperationQueues sharedOperationQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
[data writeToFile:path atomically:YES];
Then loaded in the drawMapRect method.
I tried fixing this with the following code:
AppDelegate:
int cacheSizeMemory = 4*1024*1024; // 4MB
int cacheSizeDisk = 32*1024*1024; // 32MB
NSURLCache *sharedCache = [[NSURLCache alloc] initWithMemoryCapacity:cacheSizeMemory diskCapacity:cacheSizeDisk diskPath:#"nsurlcache"];
[NSURLCache setSharedURLCache:sharedCache];
NSURLCache *URLCache = [[NSURLCache alloc] initWithMemoryCapacity:cacheSizeMemory
diskCapacity:cacheSizeDisk
diskPath:nil];
[NSURLCache setSharedURLCache:URLCache];
ViewController:
- (void)didReceiveMemoryWarning
{
[[NSURLCache sharedURLCache] removeAllCachedResponses];
[super didReceiveMemoryWarning];
}
right after the request: [added]
[[NSURLCache sharedURLCache] removeCachedResponseForRequest:request];
But as you can see in Instruments without any luck.
Could this be my problem?
Is this the NSURLCache which is growing or something else?
As requested a couple more screenshots from instruments:
First, 400 network requests in one minute seems pretty excessive. Some of those requests are probably duplicated or unnecessary. The amount of calls is obviously downloading a lot of information, and not giving the os much time to cleanup.
Second, your NSURLCache is actually providing more memory space than the default cache. I tested on my device/simulator and ios provides a default memory capacity of 512 000 bytes. You're caches are initialized with 4 194 304 bytes (and way more on disk).
I would suggest that you set your cache size smaller to see some improvement. However, investigating the amount of network requests that are made will provide longer term benefits.

NSURLCache does not clear stored responses in iOS8

Here is the sample function I call when i need to clear cache and make a new call to URL
- (void)clearDataFromNSURLCache:(NSString *)urlString
{
NSURL *requestUrl = [NSURL URLWithString:urlString];
NSURLRequest *dataUrlRequest = [NSURLRequest requestWithURL: requestUrl];
NSURLCache * cache =[NSURLCache sharedURLCache];
NSCachedURLResponse* cacheResponse =[cache cachedResponseForRequest:dataUrlRequest];
if (cacheResponse) {
NSString* dataStr = [NSString stringWithUTF8String:[[cacheResponse data] bytes]];
NSLog(#"data str r= %#",dataStr);
NSLog(#"url str r= %#",[[[cacheResponse response] URL] absoluteString]);
[cache storeCachedResponse:nil forRequest:dataUrlRequest];
[NSURLCache setSharedURLCache:cache];
}
[[NSURLCache sharedURLCache] removeCachedResponseForRequest:dataUrlRequest];
//Check if the response data has been removed/deleted from cache
NSURLRequest *finalRequestUrlRequest = [NSURLRequest requestWithURL:requestUrl];
NSURLCache * finalCache =[NSURLCache sharedURLCache];
NSCachedURLResponse* finalcacheResponse =[finalCache cachedResponseForRequest:finalRequestUrlRequest];
if (finalcacheResponse) {
//Should not enter here
NSString* finaldataStr = [NSString stringWithUTF8String:[[finalcacheResponse data] bytes]];
NSLog(#"data str r= %#",finaldataStr);
NSLog(#"url str r= %#",[[[cacheResponse response] URL] absoluteString]);
}
}
In iOS 6/7 the response is deleted successfully for the requestURL, but in iOS 8 it never gets deleted.
I have searched but could not find any reason why this should not work in iOS8.
Any help will be appreciated…..
NSURLCache is broken on iOS 8.0.x - it never purges the cache at all, so it grows without limit. See http://blog.airsource.co.uk/2014/10/11/nsurlcache-ios8-broken/ for a detailed investigation. Cache purging is fixed in the 8.1 betas - but removeCachedResponseForRequest: is not.
removeCachedResponsesSinceDate: does appear to work on iOS 8.0 - an API that was added for 8.0, but hasn't made it to the docs yet (it is in the API diffs). I am unclear what use it is to anyone - surely what you normally want to do is remove cached responses before a particular date.
removeAllCachedResponses works as well - but that's a real sledgehammer solution.
I got a sufficient result reseting the cached response for a specific URL, changing the cache control to something that would never be returned like a "max-age=0" in the header. Look here
Whenever any API call is generated, That response is saved in the cache. You are able to find that folder in your documents directory, a folder with named cachedb is created which contains a list of responses. It can be a major concern related to security. With any third-party tool, someone can have access to that information.
Below is the way I have solved this issue :
NSURLCache *cache = [[NSURLCache alloc] initWithMemoryCapacity:0 * 1024 * 1024 diskCapacity:0 * 1024 * 1024 diskPath:nil];
[NSURLCache setSharedURLCache:cache];
I have allocated 0 memory space to the cache. so no data will be stored in Cache memory.

Internet data doesn't update correctly

I've got this weird issue with my apps that uses internet connection. The app doesn't seem to update the data from internet in the right way. I've got a UIWebView with a simple chat. When I write a message in the chat with safari or in my web browser everything works fine. When writing something in the chat in the app, the data doesn't update, even when reloading the page.
It updates totally un-logically as well. Even when restarting the app the new data isn't shown, then all of a sudden it shows.
Had the same issue with another app too, which was not handled by a UIWebView. Any idea what it might be?
Example code:
- (void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
NSString *username = [[Database singletonDataBase] currentUserName];
NSString *urlAddress = [NSString stringWithFormat:#"%#?name=%#", #"http://webapi.com/index.php", username];
NSURL *url = [NSURL URLWithString:urlAddress];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
[self.webView loadRequest:requestObj];
}
In your app delegates, didFinishLoading method, set the NSURLCache to not cache the data:
// Remove and disable all URL Cache, but doesn't seem to affect the memory
[[NSURLCache sharedURLCache] removeAllCachedResponses];
[[NSURLCache sharedURLCache] setDiskCapacity:0];
[[NSURLCache sharedURLCache] setMemoryCapacity:0];
If that doesn't work, you can also try setting the cache policy on the NSURLRequest:
NSURL *url = [NSURL URLWithString:urlAddress];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url
cachePolicy:NSURLRequestReloadIgnoringCacheData
timeoutInterval: 10.0];
I finally found the answer. Its nothing wrong with my code, as I thought. The problem lies on the server side. And, as they say in this thread:
NSURLConnection is returning old data
It seems to be badly configured server-side or proxy. Which makes the cache act all wierd. I tried another server and everything worked just fine!
Hope this helps someone with the same issue, cause it sure wasted me ALOT of time.

Clearing UIWebview cache

I have used UIWebview to load a web page using loadRequest: method, when I leave that scene I call [self.webView stopLoading]; and release the webView.
In activity monitor on first launch i have seen that the real memory increased by 4MB, and on multiple launches/loading the real memory doesn't increase. It is increasing only once.
I have checked the retain count of webview. It is proper i.e., 0. I think UIWebView is caching some data. How do I avoid caching or remove cached data? Or is there another reason for this?
I actually think it may retain cached information when you close out the UIWebView. I've tried removing a UIWebView from my UIViewController, releasing it, then creating a new one. The new one remembered exactly where I was at when I went back to an address without having to reload everything (it remembered my previous UIWebView was logged in).
So a couple of suggestions:
[[NSURLCache sharedURLCache] removeCachedResponseForRequest:NSURLRequest];
This would remove a cached response for a specific request. There is also a call that will remove all cached responses for all requests ran on the UIWebView:
[[NSURLCache sharedURLCache] removeAllCachedResponses];
After that, you can try deleting any associated cookies with the UIWebView:
for(NSHTTPCookie *cookie in [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies]) {
if([[cookie domain] isEqualToString:someNSStringUrlDomain]) {
[[NSHTTPCookieStorage sharedHTTPCookieStorage] deleteCookie:cookie];
}
}
Swift 3:
// Remove all cache
URLCache.shared.removeAllCachedResponses()
// Delete any associated cookies
if let cookies = HTTPCookieStorage.shared.cookies {
for cookie in cookies {
HTTPCookieStorage.shared.deleteCookie(cookie)
}
}
Don't disable caching completely, it'll hurt your app performance and it's unnecessary. The important thing is to explicitly configure the cache at app startup and purge it when necessary.
So in application:DidFinishLaunchingWithOptions: configure the cache limits as follows:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
int cacheSizeMemory = 4*1024*1024; // 4MB
int cacheSizeDisk = 32*1024*1024; // 32MB
NSURLCache *sharedCache = [[NSURLCache alloc] initWithMemoryCapacity:cacheSizeMemory diskCapacity:cacheSizeDisk diskPath:#"nsurlcache"];
[NSURLCache setSharedURLCache:sharedCache];
// ... other launching code
}
Once you have it properly configured, then when you need to purge the cache (for example in applicationDidReceiveMemoryWarning or when you close a UIWebView) just do:
[[NSURLCache sharedURLCache] removeAllCachedResponses];
and you'll see the memory is recovered. I blogged about this issue here: http://twobitlabs.com/2012/01/ios-ipad-iphone-nsurlcache-uiwebview-memory-utilization/
You can disable the caching by doing the following:
NSURLCache *sharedCache = [[NSURLCache alloc] initWithMemoryCapacity:0 diskCapacity:0 diskPath:nil];
[NSURLCache setSharedURLCache:sharedCache];
[sharedCache release];
ARC:
NSURLCache *sharedCache = [[NSURLCache alloc] initWithMemoryCapacity:0 diskCapacity:0 diskPath:nil];
[NSURLCache setSharedURLCache:sharedCache];
Swift 3.
// Remove all cache
URLCache.shared.removeAllCachedResponses()
// Delete any associated cookies
if let cookies = HTTPCookieStorage.shared.cookies {
for cookie in cookies {
HTTPCookieStorage.shared.deleteCookie(cookie)
}
}
I could not change the code, so I needed command line for testing purpose and figured this could help someone:
Application specific caches are stored in ~/Library/Caches/<bundle-identifier-of-your-app>, so simply remove as below and re-open your application
rm -rf ~/Library/Caches/com.mycompany.appname/
My educated guess is that the memory use you are seeing is not from the page content, but rather from loading UIWebView and all of it's supporting WebKit libraries. I love the UIWebView control, but it is a 'heavy' control that pulls in a very large block of code.
This code is a large sub-set of the iOS Safari browser, and likely initializes a large body of static structures.
After various attempt, only this works well for me (under ios 8):
NSURLCache *cache = [[NSURLCache alloc] initWithMemoryCapacity:1 diskCapacity:1 diskPath:nil];
[NSURLCache setSharedURLCache:cache];
For swift 2.0:
let cacheSizeMemory = 4*1024*1024; // 4MB
let cacheSizeDisk = 32*1024*1024; // 32MB
let sharedCache = NSURLCache(memoryCapacity: cacheSizeMemory, diskCapacity: cacheSizeDisk, diskPath: "nsurlcache")
NSURLCache.setSharedURLCache(sharedCache)
I am loading html pages from Documents and if they have the same name of css file UIWebView it seem it does not throw the previous css rules. Maybe because they have the same URL or something.
I tried this:
NSURLCache *sharedCache = [[NSURLCache alloc] initWithMemoryCapacity:0 diskCapacity:0 diskPath:nil];
[NSURLCache setSharedURLCache:sharedCache];
[sharedCache release];
I tried this :
[[NSURLCache sharedURLCache] removeAllCachedResponses];
I am loading the initial page with:
NSURLRequest *appReq = [NSURLRequest requestWithURL:appURL cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:20.0];
It refuses to throw its cached data! Frustrating!
I am doing this inside a PhoneGap (Cordova) application. I have not tried it in isolated UIWebView.
Update1: I have found this.
Changing the html files, though seems very messy.

Resources