I want to download a page and show this in WEBVIEW local, but the images are missing. The images are only shown, when I'm online, in offline mode they are missing. How can I solve this? This is the code I used up until now:
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
{
NSURL *url = [NSURL URLWithString:#"http://livedemo00.template-help.com/wt_37587/index.html"];
//[WEBVIEW loadRequest:reqURL];
// Determile cache file path
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *filePath = [NSString stringWithFormat:#"%#/%#", [paths objectAtIndex:0],#"index.html"];
// Download and write to file
NSData *urlData = [NSData dataWithContentsOfURL:url];
[urlData writeToFile:filePath atomically:YES];
// Load file in UIWebView
[WEBVIEW loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:filePath]]];
[super viewDidLoad];
}
I've been meaning to write this up for a few weeks now, and this question finally got me to do it. See Drop-in offline caching for UIWebView (and NSURLProtocol).
The short answer, in my experience, is that the easiest solution is to use an NSURLProtocol to intercept NSURLConnection requests (including the ones made by UIWebView) and write the results to disk. If the request is made when you're offline, just read the response from disk and replay it. This is extremely transparent to the rest of the application, and avoids all kinds of edge-cases related to subclassing NSURLCache. (For more information on how to subclass NSURLCache see Substituting local data for remote UIWebView requests on Cocoa With Love, and AFCache.)
My NSURLProtocol approach is very simple, and is not a general-purpose caching solution. It's just intended to assist a UIWebView when you're offline. But for that, I think it solves the problem well.
Related
I have a UIWebView where I display dynamically generated HTML via
[_webView loadHTMLString:htmlString baseURL:applicationDocumentsDirectory];
The HTML contains images such as <img src="chart1.png">. Each time the HTML is generated, the images are also freshly generated. (I have checked that they are indeed in the right location and updated.) However, after the first run, if I change the data and relaunch my UIWebView, it uses the old images.
I have tried:
[[NSURLCache sharedURLCache] removeAllCachedResponses];
to no avail. (Not surprising, maybe, as this relates to NSURLRequests.)
I know that there is the possibility of absolute URLs, but I have not tried this at it seems cumbersome and I want it to work with these simple relative URLs. The issue is not finding the images but updating them appropriately.
I also know that you could invent some scheme tricking the browser into thinking that the image is dynamic by changing the src to something like chart1.png?1234 where the number is random generated and always unique. This also seems like a useless workaround for an issue that should be simple to solve.
Any ideas?
You should have a proper reference to the image, otherwise it may not work. If you have the image and the html file in the same level then try using something like this,
<img src="./chart1.png">
Or if you want the images inside the folder then refer it using the proper path reference to it.
I hope it works.
hi i was having a similar problem with uiwebview whenever i loaded a previously loaded page old content was displayed. after investigating further i found that uiwebview content is loaded in the background and then displayed after its finished loading; however while it is loading old content is displayed. I fixed my problem by making my own uiwebview loading delegates and adding my own loading symbol insteaad of displaying old content.
-(void)webViewDidStartLoad:(UIWebView *)webView{
webView.hidden = true;
loader.animationImages =[NSArray arrayWithObjects:
[UIImage imageNamed:#"1.png"],
[UIImage imageNamed:#"2.png"],
[UIImage imageNamed:#"3.png"],
[UIImage imageNamed:#"4.png"],
[UIImage imageNamed:#"3.png"],
[UIImage imageNamed:#"2.png"],
[UIImage imageNamed:#"1.png"],
[UIImage imageNamed:#"5.png"]
,nil];
loader.animationDuration = 1.5;
loader.animationRepeatCount = 100;
[loader startAnimating];
}
-(void)webViewDidFinishLoad:(UIWebView *)webView{
[loader stopAnimating];
webView.hidden = false;
}
remember to link the delegates and all that other stuff
i hope this helps :)
You need to provide the absolute path of the image source.
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString* path = [documentsDirectory stringByAppendingPathComponent:
#"/chart1.png" ];
I hope this works
I need to save the contents of blogs loaded on the webview for offline reading. Does webview support caching and if it does, how much is the size it can cache? Currently I am loading the webview as follows:
NSURL *url = [NSURL URLWithString:_entry.articleUrl];
_webView.delegate =self;
[_webView loadRequest:[NSURLRequest requestWithURL:url]];
I get the resposnse in
- (void)webViewDidFinishLoad:(UIWebView *)webView
but could not find anywhere in UIWebView's documentation where I can find the data loaded in that webView. Any help will be greatly appreciated.
NSData *cacheUrlData = [NSData dataWithContentsOfURL:url];
Save this NSData anywhere you want. Preferably in dictionary with the key=url and value= cacheUrlData and write this dictionary to a plist file in Documents Directory..
i would like to download a bunch of pdf's from a website to the iPhone filesystem in my app.
Because i don't want to download the files everytime i start the app.
In the documentation i found a function called "dataWithContentsOfURL" but the sample code didn't help me. Is this the right way, or is there an easier solution?
Can someone give me a tip or two ? ;-)
greets max
I recommend using ASIHTTPRequest, it's well written, documented and easy to use, heres a quick example from one of my applications download class that downloads a JSON file using ASIHTTPRequest:
-(void)downloadJSONData:(NSString *)path destination:(NSString *)destination secure:(BOOL)secure {
if (![self queue]) {
[self setQueue:[[[NSOperationQueue alloc] init] autorelease]];
}
NSFileManager *fileManager = [NSFileManager defaultManager];
[fileManager removeItemAtPath:destination error:NULL];
NSURL *url = [NSURL URLWithString:path];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
if(secure){
[request addRequestHeader:#"Authorization" value:[NSString stringWithFormat:#"Basic %#",[ASIHTTPRequest base64forData:[[NSString stringWithFormat:#"%#:%#",self.username,self.password] dataUsingEncoding:NSUTF8StringEncoding]]]];
}
[request setDelegate:self];
[request setDidFinishSelector:#selector(requestDone:)];
[request setDidFailSelector:#selector(requestWentWrong:)];
[request setDownloadDestinationPath:destination];
[[self queue] addOperation:request]; //queue is an NSOperationQueue
}
I would take a look at the how-to-use page as it contains everything you need to know.
You're on the right track
-(void)downloadURL:(NSURL *)theUrl toLocalFileURL:(NSURL *)localURL
{
NSData *dlData = [NSData dataWithContentsOfURL:theURL];
[dlData writeToURL:localURL atomically:YES];
}
So just research how NSURLs are created for local and remote objects and you're all set.
Yes you could download files only as you need(Lazy load).
When ever you want access the files. Check in the documents directory for the file. In the second answer it is being specified. Append file name with the douments path. Check If there is a readable file using NSFileManager's isReadableFileAtPath:instance method. if it returns false then initiate downloading the pdf from the website.
Please do care to create a class which downloads file asynchronously. You could use NSURLconnection to initiate the request and its delegate methods to process its content After downloading content write it to documents folder.
If you could create a class for asynchronous download , you could initiate parallel downloads and use maximum use of the bandwidth.
By making asynchronous downloads you could make sure that you application is responsive even while files are getting downloaded.
http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSFileManager_Class/Reference/Reference.html
http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSURLConnection_Class/Reference/Reference.html
Regards ,
Jackson Sunny Rodrigues
Do not use dataWithContentsOfURL: unless you're executing it somewhere other than the main thread. It is a blocking API as well as one that accesses the network. That is a recipe for bad user experience.
Think about this: You use a blocking API to access the network, but the network is down or really slow. The main thread is now blocked, so your user interface is not responding to user interaction. The user gets frustrated and tries to cancel the download using the handy button you put on the UI, but "OH NO!" it doesn't work because the UI is blocked.
Do not use blocking APIs on the main thread.
You should look at the documentation for NSURLConnection and it's asynchronous loading methods for downloading data.
You should use
NSData* pdf_data = [NSData dataWithContentsOfFile: #"file_path"];
where file_path is the path where you've saved your file (it is usually Documents or Library directories).
To save data there use:
[pdf_data writeToFile: #"file_path" atomically: YES];
To get path to your documents directory you can use:
- (NSString *)applicationDocumentsDirectory {
NSArray *paths =
NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
return basePath;
}
I am using the following (simple) code to load a PDF from the documents folder in my app into a UIWebView. The performance is very poor. I tried loading the same PDF from the web via Safari and the performance was great. Does anyone have any ideas? (this viewController is being presented as a modalViewController).
- firstView.m
InfoViewController *mcontroller = [[InfoViewController alloc] init];
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *docsPath = [paths objectAtIndex:0];
NSString *pathToPDF = [NSString stringWithFormat:#"%#/myPDF.PDF",docsPath];
NSURL *targetURL = [NSURL fileURLWithPath:pathToPDF];
mcontroller.urlToFile = targetURL;
[self presentModalViewController:mcontroller animated:YES];
modalViewController.m -
- (void)viewDidLoad {
[super viewDidLoad];
NSURLRequest *request = [NSURLRequest requestWithURL:urlToFile];
[webView loadRequest:request];
}
I ended up using the documentInteractionController for this to display the PDF in Quick Look. There is a great tutorial for this in the 2010 WWDC vids.
No idea why it wasn't working well in webView, but it's smooth as silk in Quick Look.
The first thing I would look at is the PDF its self. Often people try loading huge PDF files and expect them to perform wonderfully. Can you post the PDF for us to see? How large is the file? Remember that the PDF file size is the compressed size, to display images in the PDF they will be uncompressed when stored in RAM. Its not uncommon for a 500KB image on disk to use 20 MB in memory (This applies for all raster graphics, not just PDFs). This is usually the case when PDF performance is poor from what I've seen around here.
I know you said it works great in Safari, however we don't know what all Apple does in Safari's internals vs a UIWebView. Also Safari is usually running in the background, so it is using memory even when your app is running. This reduces mem that you app can use, but when you are running safari as the foremost app, 3rd party apps aren't using much memory, so safari could potentially cache more of the PDF at a time.
Is it possible to preload content of a local file with embedded images for a UIWebView?
This is how I'm loading the data inside the UIWebView:
NSString *urlString = [[NSBundle mainBundle] pathForResource:#"info" ofType:#"html"];
NSString *htmlContent = [NSString stringWithContentsOfFile:urlString encoding:NSUTF8StringEncoding error:nil];
[myWebView loadHTMLString:htmlContent baseURL:nil];
But the UIWebView still needs some time to display the content. Is there any way to put this content into the browser cache on app start?
If you create the browser object on app start and load the HTML string immediately, it should work fine to display the view later.
Another option would be to allocate it when necessary, but not actually show the view until it's done loading (wait for - (void)webViewDidFinishLoad:(UIWebView *)webView to be called on the web view's delegate before showing it).
Also, would it make more sense to call
[myWebView loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:urlString]]];
than using the loadHTMLString: method? That way, you don't have to load the HTML string into memory yourself and the web view can load it directly from disk.