I'm loading a remote webpage into an iOS webview which relies on js and css assets. To improve the performance particularly on 3G networks, I'm hoping to call these assets from files local to the iOS device.
The website backing the iOS app is also used by mobile phone browsers, not just the iOS app, so subclassing NSURLRequest to register my own URL prefix (myurl://) is not ideal.
I already have code that launches mobileSafari for URLs outside of my domain:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
NSURL *url = [request URL];
NSString *hostname = [url host];
if (![hostname hasSuffix:#".mysite.com"] && navigationType == UIWebViewNavigationTypeLinkClicked) {
[[UIApplication sharedApplication] openURL:url];
return NO;
}
return YES;
}
This method is called from the same controller implementation with code like this:
- (void)viewDidLoad {
[super viewDidLoad];
// ...
webView.delegate = self;
// ...
NSURL *url = [[NSURL alloc] initWithString:([path length] > 0 ? path : #"http://mysite.com/mobile/index")];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
[webView loadRequest:request];
// ...
}
I've reviewed several other questions ( How to use an iPhone webView with an external HTML that references local images? , Dynamically loading javascript files in UIWebView with local cache not working, iOS WebView remote html with local image files, Using local resources in an iPhone webview ) but they all seem to miss a key element to my problem.
The first link has the start of something promising:
if ([url isEqualToString:#"http://path-to-cdn.com/jquery-1.8.2.min.js"]) {
fileToLoad = [[NSBundle mainBundle] pathForResource:#"jquery-1.8.2.min" ofType:#"js"];
}
If that's a sensible approach, I'm stuck on how to get from passing that fileToLoad NSBundle into the webView's loadRequest, since that's expecting a URL.
I think I'm on the right path after realizing that I could use the output of stringByAppendingPathComponent as a URL, like so...
if (![hostname hasSuffix:#".mysite.com"] && navigationType == UIWebViewNavigationTypeLinkClicked) {
NSString *urlString = [url absoluteString];
if ([urlString isEqualToString:#"http://path-to-cdn.com/jquery-1.8.2.min.js"]) {
NSString *tempurl = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"js/jquery-1.8.2.min.js"];
[webView loadRequest:[NSMutableURLRequest requestWithURL:tempurl]];
} else {
[[UIApplication sharedApplication] openURL:url];
}
return NO;
}
return YES;
I don't have it working yet (it's still loading the remote URL) but I think I'm on the right path.
Related
Im working on a web based application, it contains only one webView, the code below:
- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType {
if ((navigationType == UIWebViewNavigationTypeLinkClicked )) {
[[UIApplication sharedApplication] openURL:[request URL]] ;
}
HUD = [[MBProgressHUD alloc] initWithView:self.view];
[self.view addSubview:HUD];
// Set determinate mode
[HUD show:YES];
//CAPTURE USER LINK-CLICK.
NSURL *url = [request URL];
NSString *urls= [url absoluteString];
NSString *code = [urls substringFromIndex: [urls length] - 1];
if ( [urls containsString:#".html"] && ![code isEqualToString:#"#"] ) {
_webView.hidden= YES;
}
this code will open all the web views on safari , but i only need to open specific URLs on safari
for example :
http://xxxx/residential/ this must be opened on safari, while all the other pages should be opened on webView inside the application.
Any help
First thing is that you want to open specific urls that should open in Safari instead of UIWebView. But there is not any conditions that fulfill your requirement.
First check your [request url] with your desired url. If both matched then open that url in SFSafariViewController instead of openUrl function. in else conditon you can load your [request url] which you don't want to open in Safari.
NSString *testString =[NSString stringWithFormat:#" Google"];
[webView loadHTMLString:testString baseURL:nil];
I want to get the URL when I click on this UIWebView content in
-(BOOL) webView:(UIWebView *)inWeb shouldStartLoadWithRequest:(NSURLRequest *)inRequest navigationType:(UIWebViewNavigationType)inType {
if ( inType == UIWebViewNavigationTypeLinkClicked ) {
[[UIApplication sharedApplication] openURL:inRequest.mainDocumentURL];
return NO;
}
return YES;
}
delegate method.
When I click google hyperlink in webview it gives
URL: applewebdata://
Please help me.
You question is not very clear if you want to get the tapped url on webview or the webview's loaded page url ,
If you want to get webview loaded page url you can use NSURLRequestObject,something like
NSString * url = [request URL];
If you want to get the clicked link url , you will have to use this java script
NSString *url = [webView stringByEvaluatingJavaScriptFromString:#"window.location"];
you can do like this way
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
if ([request.URL.absoluteString rangeOfString:#"www.google.com"].location!=NSNotFound)
{
[[UIApplication sharedApplication]openURL:request.URL];
return NO;
}
return YES;
}
For Swift:
Whenever your webpage is loaded you can use this, I use it for a label in this case:
webUrlLabel.text = webView.request.URL.absoluteString
For Objective-C:
NSString *currentPage = [NSString stringWithFormat:#"%#", webView.request.URL.absoluteString];
webUrlLabel is a UILabel
webView is my UIWebView
You already have NSURLRequest object. Access url from that.
inRequest.URL
way 1:
NSString *currentURL = myWebView.request.URL.absoluteString;
Way 2:
- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType {
//CAPTURE USER LINK-CLICK.
NSURL *url = [request URL];
yourTextBox.text = [url absoluteString];
return YES;
}
Please let me know if it works. Thanks
I have looked everywhere and have not found exactly what I am looking for, so here is my question:
I have a basic app I am playing around with. I have created a webview and would like to be able to download a file from the website that loads in the webview and save the file to say the Downloads folder on the local machine. The site loads fine inside the webview, now how do I download a file, say an .xml file from the site and save it to the Downloads folder on the local machine?
This is what I have so far:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
NSURL *url = [NSURL URLWithString:#"http://www.google.com"];//<-- example site
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[[webView mainFrame] loadRequest:request];
}
I would like to be able to download a file (possible using a delegate) then save it to a location on the local computer. I am pretty new to this so I'd appreciate any help.
The issue has been resolved. I added the following code to make it work:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
NSURL *url = [NSURL URLWithString:#"http://www.google.com"]; // <-- example website
NSURLRequest *request = [NSURLRequest requestWithURL:url];
self.webView.policyDelegate = self;
[self.webView setDownloadDelegate:self];
[[self.webView mainFrame] loadRequest:request];
}
- (void)webView:(WebView *)webView decidePolicyForMIMEType:(NSString *)type
request:(NSURLRequest *)request
frame:(WebFrame *)frame
decisionListener:(id < WebPolicyDecisionListener >)listener
{
if([type isEqualToString:#"application/octet-stream"]) //this is the type I was looking for
{
//figure out how to save file here
[listener download];
NSURLDownload *downLoad = [[NSURLDownload alloc] initWithRequest:request delegate:self];
if(downLoad)
{
[self download:downLoad decideDestinationWithSuggestedFilename:#"filename.ext"];
NSLog(#"File Downloaded Succesfully");
//[webView close];
[self.window close];
}
else
{
NSLog(#"The download failed");
}
}
//just ignore all other types; the default behaviour will be used
}
-(void)download:(NSURLDownload *)download decideDestinationWithSuggestedFilename:(NSString *)filename
{
NSString *destinationFileName;
NSString *homeDirectory = NSHomeDirectory();
destinationFileName = [[homeDirectory stringByAppendingPathComponent:#"Documents"] stringByAppendingPathComponent:filename];
[download setDestination:destinationFileName allowOverwrite:NO]; //file is being saved to the Documents folder on the local machine
}
Hope this will be helpful to someone else.
I am loading a local HTML into a UIWebView as follows :
- (void)viewDidLoad
{
[super viewDidLoad];
//Setup our UIWebView
webView = [[UIWebView alloc] initWithFrame:self.view.bounds];
webView.delegate = self;
webView.scalesPageToFit = YES;
webView.userInteractionEnabled = YES;
[self.view addSubview:webView];
...
[self loadWebPage];
}
- (void)loadWebPage {
NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"index" ofType:#"html"]];
[webView loadRequest:[NSURLRequest requestWithURL:url]];
}
And in the header :
#interface ViewController : UIViewController <UIWebViewDelegate>
However for some reason my webview delegates are not being called :
- (void)webViewDidStartLoad:(UIWebView *)webView {
NSLog(#"Starting HTML Load Process");
}
- (void)webViewDidFinishLoad:(UIWebView *)webViewRef {
NSLog(#"Web View Finished Loading Method");
}
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
NSLog(#"Error loading HTML ! %#", error);
}
Can anyone suggest why ?
Thanks !
Called the method [self loadWeb];
But on definition the method is - (void)loadWebPage;
Is it typo?
The only way I can reproduce is this by declaring the webView #property as weak. Can you confirm you are declaring it as a strong reference?
how did you declare your UIWebView instance variable, as a strong or weak? If weak make it strong.
The problem is that this call.
NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"index" ofType:#"html"]];
Looks like you're loading the HTML from inside your bundle. This means you need to confirm that all the additional files (.js, .css, and any media files) also need to be present in your bundle.
So the first thing need to check fileURLWithPath: point either it's returning nil or not. If it's not then it means that .html page resolved, however the additional files not resolved as part of the request because it's not placed on the same "index.html" path.
First you need to confirm the directory structure of your "index.html" and all the additional files used inside the page. In order to do that, you have to right click on binary .app in your "build" directory in the finder and then select "Show Package contents".
binary (.app) > right click > Show Package contents
This shows what the app's main bundle contains. Look inside for your HTML file. If it's in a folder, that folder name needs to be in the inDirectory parameter of the pathForResource call. If it's on the top-level then you don't have a folder reference. Either delete & re-drag it into project or use the pathForResource version without inDirectory.
The best way to don't setup the base path or relative path for the resources inside .html page (.js, .css and images) because it don't work. Copy all the additional resources next to "index.html" file so it would be easy to resolve on runtime from bundle.
NSString *path = #"<Index.html Path>";
NSURL *url = [NSURL URLWithString: [path lastPathComponent]
relativeToURL: [NSURL fileURLWithPath: [path stringByDeletingLastPathComponent]
isDirectory: YES]];
Try this
NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"index" ofType:#"html"]isDirectory:NO];
I am currently using ChildBrowser in phoneapp to open a website. However, I would like to open all external links of this website to open in Safari.
I do not have control over the source of this website.
My understanding is that I have to modify ChildBrowser to open all links starting with "http" in Safari.
I can't exactly read Objective-C, but I believe the code below is relevant.
- (void)loadURL:(NSString*)url
{
NSLog(#"Opening Url : %#",url);
if( [url hasSuffix:#".png" ] ||
[url hasSuffix:#".jpg" ] ||
[url hasSuffix:#".jpeg" ] ||
[url hasSuffix:#".bmp" ] ||
[url hasSuffix:#".gif" ] )
{
[ imageURL release ];
imageURL = [url copy];
isImage = YES;
NSString* htmlText = #"<html><body style='background-color:#333;margin:0px;padding:0px;'><img style='min-height:200px;margin:0px;padding:0px;width:100%;height:auto;' alt='' src='IMGSRC'/></body></html>";
htmlText = [ htmlText stringByReplacingOccurrencesOfString:#"IMGSRC" withString:url ];
[webView loadHTMLString:htmlText baseURL:[NSURL URLWithString:#""]];
}
else if ( [url hasPrefix:#"http" ])
{
//I have added in this else if.
}
else
{
imageURL = #"";
isImage = NO;
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];
[webView loadRequest:request];
}
webView.hidden = NO;
}
Any advice?
The easiest way I've found to do this is, if you know the Domain Host name that you will initially be requesting with childBrowser and you don't plan on requesting any other Domains then you can write this event right into the ChildBrowserViewController.m file.
- (BOOL)webView:(UIWebView *)theWebView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
NSURL *url = [request URL];
NSString* domain = [url host];
// Intercept the external http requests and forward to Safari.app
// Otherwise forward to the PhoneGap WebView
if ([[url scheme] isEqualToString:#"http"] || [[url scheme] isEqualToString:#"https"] || [[url scheme] isEqualToString:#"www"]) {
if ( [domain isEqualToString:#"YOURDOMAIN.NAME] ) {
return YES;
} else {
[[UIApplication sharedApplication] openURL:url];
return NO;
}
} else {
return YES;// [ super webView:theWebView shouldStartLoadWithRequest:request navigationType:navigationType ];
}
}
This will catch all requests made by childBrowser and if they match standard URL convention (preceding with HTTP, HTTPS, or WWW) and they are not your Domain Host name that you preset then it will foce them to open in Safari. Then when the user returns to your app they will still be on the previous page they where when they clicked the link.
I messed with this for hours until I came up with this.
If you need to be able to open more than one Domain Host with childBrowser but still want each one to open all external links leading away from that current domain in Safari I would suggest the following.
Add the following to ChildBrowserViewController.h
BOOL scaleEnabled;
BOOL isImage;
NSString* originalURL; <- THIS RIGHT HERE
NSString* imageURL;
And this
#property(retain) NSString* imageURL;
#property(retain) NSString* originalURL; <- THIS RIGHT HERE
#property(assign) BOOL isImage;
Then add the following to ChildBrowserViewController.m
#synthesize imageURL;
#originalURL; <- THIS RIGHT HERE
#synthesize supportedOrientations;
#synthesize isImage;
And add the following
- (void)loadURL:(NSString*)url
{
originalURL = url; <- THIS RIGHT HERE
NSLog(#"Opening Url : %#",url);
And then in the method I posted above change the following
NSURL *url = [request URL];
NSString* domain = [url host];
NSURL *oURL = [NSURL URLWithString: originalURL]; <- THIS RIGHT HERE
NSString* oDomain = [oURL host]; <- THIS RIGHT HERE
// Intercept the external http requests and forward to Safari.app
// Otherwise forward to the PhoneGap WebView
if ([[url scheme] isEqualToString:#"http"] || [[url scheme] isEqualToString:#"https"] || [[url scheme] isEqualToString:#"www"]) {
if ( [domain isEqualToString:oDomain] ) { <- THIS RIGHT HERE
return YES;
} else {
I haven't tested this second part but it should work just fine.
Good luck.