So i have an app that is not so much a webapp but more uses UIViewControllers and UIViews for most screens. On one particular controller i have a UIWebView control that only occupies a small portion of the UIViewController screen real estate that i load html from a web service as a string.
[self.webView loadHTMLString:marketingBlurb baseURL:nil];
what i'm wondering is if the html links in this string can open up on the browser and not in the UIWebView in my app???? How can i do this?? Is this even possible ?
Set the delegate of the webview to self, and intercept all links using webView:shouldStartLoadWithRequest:navigationType:
You can then call [UIApplication openURL] to open Safari.
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
if (navigationType == UIWebViewNavigationTypeLinkClicked) {
[[UIApplication sharedApplication] openURL:[request URL]];
return NO;
}
return YES;
}
I didn't test this code, but it will get you started.
Related
I am relatively new to Xcode and I have started building an app that uses UIWebView. To make it compliant for App Store submission, Apple prefers you use Safari. To overcome this problem I want to add a button to my UIWebView navigation that, when clicked, will open the same url in Safari. An example of this can be seen in the Twitter app; they have a button that opens the currently viewed UIWebView in a Safari window.
You can use the UIWebViewDelegate's method
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
if iWantToOpenThisURLInSafari([request URL]) {
[UIApplication openUrl:[request URL]];
return NO; // tell the webView to not navigate to the URL, I'm handling it
} else {
return YES;
}
}
- (BOOL)iWantToOpenThisURLInSafari:(NSURL* url) [
// you just have to fill in this method.
return NO;
}
http://developer.apple.com/library/ios/#documentation/uikit/reference/UIWebViewDelegate_Protocol/Reference/Reference.html#//apple_ref/occ/intf/UIWebViewDelegate
EDIT: more details as requested by #PaulGraham
// You have a pointer to you webView somewhere
UIWebView *myWebView;
// create a class which implements the UIWebViewDelegate protocol
#interface MyUIWebViewDelegate:NSObject<UIWebViewDelegate>
// in this class' #implementation, implement the shouldStartLoad..method
#implementation
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
if iWantToOpenThisURLInSafari([request URL]) {
[UIApplication openUrl:[request URL]];
return NO; // tell the webView to not navigate to the URL, I'm handling it
} else {
return YES;
}
}
// then, set the webView's delegate to an instance of that class
MyUIWebViewDelegate* delegate = [[MyUIWebViewDelegate alloc] init];
webView.delegate = delegate;
// your delegate will now recieve the shouldStartLoad.. messages.
I have been having a rough time trying to open links that a user clicks in a simple web view instead of multitasking and going to safari. It is quite a pain for my users to have to leave the app every time a link is clicked and I know it is probably quite simple but still am having a terrible time making this happen. Here is the code I am using but still when the link is clicked it opens safari.
If anyone can help point me in the right direction I would be greatly appreciative! Thank you!
- (void) handleURL:(NSURL*)url
{
[web loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"%#"]]];
}
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest
*)request
navigationType:(UIWebViewNavigationType)navigationType {
NSLog(#"expected:%d, got:%d", UIWebViewNavigationTypeLinkClicked, navigationType);
if (navigationType == UIWebViewNavigationTypeLinkClicked) {
[UIApplication sharedApplication] ;
return NO;
}
if (navigationType == UIWebViewNavigationTypeLinkClicked) {
[web loadRequest:[NSURLRequest requestWithURL:[NSURL
URLWithString:replyTweetText.text]]];
return YES;
}
}
I'm not sure what this bit does:
if (navigationType == UIWebViewNavigationTypeLinkClicked) {
[UIApplication sharedApplication] ;
return NO;
}
The line [UIApplication sharedApplication]; creates and returns the singleton application instance. You aren't doing anything with it.
Also, both if statements are identical, so only the first will ever be hit and the method returns NO. There is no default returned value, which is bad for a non-void function. Try this instead:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
return YES;
}
I am pretty sure that I understand how to catch a click on a UIWebView using the webView:shouldStartLoadWithRequest:navigationType: method, but my webView does not even allow me to click the link. I am using:
UIWebView *webView = [[UIWebView alloc] initWithFrame:CGRectMake(12, top, boundsSize.width - 40.0, 400.0f)];
webView.delegate = self;
webView.backgroundColor = [UIColor clearColor];
webView.opaque = NO;
webView.allowsInlineMediaPlayback = YES;
webView.dataDetectorTypes = UIDataDetectorTypeAll;
// add to subview
I am loading in an HTML string rather than loading a URL:
[webView loadHTMLString:bodyHTML baseURL:nil];
Delegate method:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
NSLog(#"Loaded");
if (navigationType == UIWebViewNavigationTypeLinkClicked) {
NSURL *url = request.URL;
NSString *urlString = url.absoluteString;
NSLog(urlString);
}
return YES;
}//end
Everytime my webview loads I DO get the "Loaded" in my logs, so I know that the delegate method is getting called. But I can never click on a link within my UIWebView and have anything happen. It does not even look like it is allowing a pressed state on the link. The link is highlighted like a link, just won't allow clicking.
Ideas?
The reason for the UIWebView not responding to touch events is most probably this line:
webView.opaque = NO;
Try setting opaque to YES.
My understanding is that for a view to respond to touch events, that view has to be returned by the call to hitTest:withEvent: during the view hierarchy traversal performed by the event delivery mechanism.
From the hitTest:withEvent: documentation:
This method ignores view objects that are hidden, that have disabled user interaction, or have an alpha level less than 0.01.
Update
Based on new info: if the UIWebView is embedded in a UIScrollView, quote from the Apple docs:
Important: You should not embed UIWebView or UITableView objects in UIScrollView objects. If you do so, unexpected behavior can result because touch events for the two objects can be mixed up and wrongly handled.
Please try with following code
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
if(navigationType==UIWebViewNavigationTypeLinkClicked)
{
[[UIApplication sharedApplication]openURL:request.URL];
return NO;
}
return YES;
}
I've got a UIWebView which shows up a couple of screens into a UINavigationController:
First View > Second View > View with UIWebView + UILabel
Now, I display a certain page in that web view, which has a link back to my app....
myapp://foofoo
I know you can set up a custom URL with (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url and some info.plist poking, but how would change the UILabel, which is one the same screen as UIWebView, by simply clicking the myapp://foofoo link?
The best way to do this would be through a custom link, and then use the UIWebView delegate method -webView:shouldStartLoadWithRequest:navigationType: to trap requests. When you see a request come through with your link in it, you know your action has been triggered.
UIWebView Expose Objective C to JavaScript
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
NSLog(#"scheme = %#",[[request URL] scheme]);
if([[[request URL] scheme]isEqualToString:#"myscheme"])
{
[messageLabel setText:#"HELLO!"];
return NO;
}
else return YES;
}
Make sure your view controller conforms to the UIWebViewDelegate protocol for this to work.
I have an small embedded UIWebView for my about-section of the app. When the user taps a link in there, the link opens in that small embedded UIWebView which of course has no navigation controls and isn't full-screen. I don't like that. Can I force it to open links with Safari instead?
You can implement the shouldStartLoadWithRequest method of the UIWebViewDelegate protocol to intercept link clicks. Inside that method you can use UIApplication's openURL method to cause the url to be opened in the appropriate application (ie. Safari for HTTP/HTTPS).
- (BOOL) webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
NSURL *url = [request URL];
if ([url isEqual:YOUR_HOME_URL_CONTSTANT])
return YES;
[[UIApplication sharedApplication] openURL:url];
return NO;
}
You should implement shouldStartLoadWithRequest of the UIWebViewDelegate. In here you can see when the UIWebView will start loading a URL. Then you can handle which should be loaded in this webView and which should be loaded by Safari.
My code looks like:
-(BOOL) webView:(UIWebView *)inWeb shouldStartLoadWithRequest:(NSURLRequest *)inRequest navigationType:(UIWebViewNavigationType)inType
{
if (inType != UIWebViewNavigationTypeLinkClicked)
{
//This was not a clicked link, so is probably the initial load
//and should be loaded in the UIWebView
return YES;
}
//This was a clicked link, so load using Safari
[[UIApplication sharedApplication] openURL:[inRequest URL]];
return NO;
}
Here I am using UIWebViewNavigationType to determine whether it was a link click, and responding appropriately.