how to add UIWebview inside a view by coding - iphone

In my app I dragged a View from the library of the interface builder and linked it to the AppDelegate.
my question is "can I add UIWebView inside the View ?"
and if make a special class (UIView class) for the view which method behaves like viewDidload ?

Yes you can add a UIWebView inside the View.
[UIWebView *aWebView =[[UIWebView alloc] initWithFrame:CGRectMake(x,y,width,height)]; aWebView.delegate=self;
[self.view addSubview:aWebView];
[aWebView release];
In the above code you set the delegate of the WebView as self. So you can use the delegate methods of UIWebView like
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
- (void)webViewDidFinishLoad:(UIWebView *)webView
Refer this link for more details.
http://developer.apple.com/library/ios/#DOCUMENTATION/UIKit/Reference/UIWebViewDelegate_Protocol/Reference/Reference.html#//apple_ref/occ/intf/UIWebViewDelegate

Yes you can simply use -
In your h file add
#interface YourView:UIView<UIWebViewDelegate>{
in your m file add
CGRect frame = CGRectMake(0,0,200,200);
UIWebView *webView =[[UIWebView alloc] initWithFrame:frame)];
webView.delegate = self;
[self addSubview:webView];

CGRect rect=CGRectMake(x,y,width,height) ;
UIWebView *webView1 =[[UIWebView alloc] initWithFrame:rect)];
webView1.delegate=self;
[self.view addSubview:webView1];
[webView1 release];

If you view's outlet is named myView:
.h file
#interface myViewController:UIViewController <UIWebViewDelegate> {
IBOutlet UIView *myView;
}
.m file
UIWebView *,myWebView = [[UIWebView alloc] initWithFrame:CGRectMake(0,0,myView.frame.size.width,myView.frame.size.height)];
myWebView.delegate = self;
[myView addSubView:myWebView];
It's not necissary to create another subclass to listen for deleagte methods of your view, i would now treat your UIView as a UIWebView and thus use UIWebView's delegate methods, like so:
- (void)webViewDidStartLoad:(UIWebView *)webView {
NSLog(#"started loading");
}
more delegate methods can be found here in the documentation. You could also use NSNotificationCenter to listen for your own events application wide if you wish to fire something in a different class when the UIWebView is loaded.

Related

Press a Button and open a URL in another ViewController

I am trying to learn Xcode by making a simple app.
But I been looking on the net for hours (days) and I cant figure it out how I make a button that open a UIWebView in another ViewController :S
first let me show you some code that I have ready:
I have a few Buttons om my main Storyboard that each are title some country codes like UK, CA and DK.
When I press one of those Buttons I have an IBAction like this:
- (IBAction)ButtonPressed:(UIButton *)sender {
// Google button pressed
NSURL* allURLS;
if([sender.titleLabel.text isEqualToString:#"DK"]) {
// Create URL obj
allURLS = [NSURL URLWithString:#"http://google.dk"];
}else if([sender.titleLabel.text isEqualToString:#"US"])
{
allURLS = [NSURL URLWithString:#"http://google.com"];
}else if([sender.titleLabel.text isEqualToString:#"CA"])
{
allURLS = [NSURL URLWithString:#"http://google.ca"];
}
NSURLRequest* req = [NSURLRequest requestWithURL:allURLS];
[myWebView loadRequest:req];
}
How do I make this open UIWebview on my other Viewcontroller named myWebView?
please help a lost man :D
Well, you've firstViewController already designed and coded, now you've to create secondViewController with a UIWebView binded in IB it self, also it have a setter NSString variable like strUrl that you need to pass at the time of pushing or presenting secondViewController, and assign it to UIWebView in viewDidLoad of secondViewController. See my answer about how to pass a NSString? Also UIWebView has its delegates method (What's delegate & datasource methods? - Apple Doc) Which you can use to handle URL request.
These are the delegate of UIWebView, if you'll going to use it, you need to give UIWebView delegate to self.
- (void)webViewDidStartLoad:(UIWebView *)webView;
- (void)webViewDidFinishLoad:(UIWebView *)webView;
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error;
firstViewController.m
- (IBAction)ButtonPressed:(UIButton *)sender {
NSURL* allURLS;
//get your URL
secondViewControlelr *secondView=[[secondViewControlelr alloc]init];
second.urlToLoad=allURLS;
[self.navigationController pushViewController:secondView animated:YES];
}
secondViewControlelr.h
//declare url and set property
NSURL *urlToLoad;
secondViewControlelr.m
- (void)viewDidLoad
{
myWebView=[[UIWebView alloc]initWithFrame:CGRectMake(0, 0, 320, 460)];
[self.view addSubview:myWebView];
NSURLRequest *urlReq=[NSURLRequest requestWithURL:self.urlToLoad cachePolicy:NSURLCacheStorageNotAllowed timeoutInterval:10];
[myWebView loadRequest:urlReq];
}

UIWebView cannot click link

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

How to load a UIWebView with a close button on top?

I currently have the following code that loads a UIWebView from another View. Now is there anyway I can have a close button?
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UIWebView *webView=[[UIWebView alloc] initWithFrame:CGRectMake(0,0,320,480)];
[self.view addSubview:webView];
NSURLRequest *urlRequest;
NSURL *urlforWebView;
urlforWebView=[NSURL URLWithString:#"http://www.google.com"];
urlRequest=[NSURLRequest requestWithURL:urlforWebView];
[webView loadRequest:urlRequest];
}
I am going to load a page built using jquery mobile, so a close button inside the page would also work fine. But on a navigation bar would be ideal. Btw, my application does not have a UINavigationBar
I would create a new sub class of UIViewController, say WebViewController with a nib. Then I would add an UINavigationBar with a close button and an UIWebView. Then to show your web view controller you can do something like:
WebViewController *webViewController = [[WebViewController alloc] init];
webViewController.loadURL = [NSURL URLWithString:#"http://www.google.com"];
[self presentModalViewController:webViewController animated:YES];
[webViewController release];
In your WebViewController you can define:
#property (nonatomic, retain) IBOutlet UIWebView *webView;
#property (nonatomic, retain) NSURL *loadURL;
- (IBAction)close:(id)sender;
and implement something like this:
- (void)viewDidLoad {
[super viewDidLoad]
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:self.loadURL];
[self.webView loadRequest:urlRequest];
}
- (IBAction)close:(id)sender {
[self dismissModalViewControllerAnimated:YES];
}
Whenever you load the UIWebView, you could run a javascript snippet on the content first.
[webView stringByEvaluatingJavaScriptFromString:#"window.close = function() { window.location = 'app://close-webview'; };"];
That just hijacks the normal behavior of window.close() and gives you chance to catch the call in your Objective-C.
Then in your UIWebViewDelegate you could listen for whatever you chose as the close url.
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
if([request.URL.absoluteString isEqualToString:#"app://close-webview"]) {
webView.hidden = YES;
// or whatever you want to do to remove the UIWebView...
return NO;
}
return YES;
}
A bit hackish, but it would allow the web developer to control the look and feel of the close button from within the HTML content.

Catching modal UIWebView links touches

I have a view controller and I am intercepting the touches on links within the web views it manages.
My main view controller has this method.
- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType
{
//I can see this request come in upon a touch
NSURL *url = request.URL;
NSString *urlString = url.absoluteString;
NSLog(#"raw: %#", urlString);
//do some stuff (like figure out what capturedFilename is)
ExplainViewController *explanation = [[ExplainViewController alloc] initWithNibName:#"ExplainViewController" bundle:nil file:capturedFilename];
[self.navigationController presentModalViewController:explanation animated:YES];
}
And this loads a modal view properly.
ExplainViewController has a webView itself. When a user touches a link within ExplainViewConroller I'd like to handle that request too (and present another modal view).
ExplainViewController has this but I get no log activity from either method (the following nor the previous):
- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType
{
NSURL *url = request.URL;
NSString *urlString = url.absoluteString;
NSLog(#"raw: %#", urlString);
}
I want to know where this link touch request is going and how I can intercept it.
Both mentioned view controllers are using this in their .h
<UIWebViewDelegate>
You mention that both view controllers conform to the UIWebViewDelegate protocol, but is the delegate outlet of the UIWebView in the nib for ExplainViewController.h set to an instance of ExplainViewController. It will not call the method unless the UIWebView delegate property is set.
- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType {
if (navigationType == UIWebViewNavigationTypeLinkClicked) {
BrowserController *browserController = [[BrowserController alloc] initWithUrl:request.URL.absoluteString];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:browserController];
[self.navigationController presentModalViewController: navController animated:YES];
[browserController release];
[navController release];
return NO;
}
return YES;
}

Throwing webview request to another webview

I have a UIViewController with a UIWebView (webview1) in it. The webview is only a few lines of text but does have a link in it. Rather than open the link, which goes to an external website, in this tiny space, I'd like to send it on to webview2, which will be a full screen. The goal is to keep the web requests within my app rather than Safari. Instead of creating another controller for webview2, I'd like to use webview1's controller.
In Webview1Controller controller, I do this in webViewLoad:
webview1.delegate = self;
Here's where I hand off the web request to webview2, which works fine:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
myapp *delegate = [[UIApplication sharedApplication] delegate];
Webview1Controller *webview1Controller = [[Webview1Controller alloc] initWithNibName:#"webview2" bundle:nil];
//self.view = webview2;'
[delegate.navigationController pushViewController: webview1Controller animated:YES];
[webview1Controller.webview2 loadRequest:request];
[webview1Controller release];
return YES;
}
In Interface Builder, I have webview2.xib File's Owner class set to Webview1Controller. It's "view" and the webview2outlet are connected. I have an IBOutlet in Webview1Controller named webview2outlet.
When i go back to webview1, it has also loaded the same request. Is there a way to stop webview1 from loading anything? If I return NO in the above method, webview1 won't render my content.
One solution is just to reload webview1 content on viewWillAppear, which works. But is there a better way?
Return NO from the delegate method.
Regarding your comment, I think what you want to do is make your delegate method check which webview is calling your controller:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
if (webView == webview1) {
Webview1Controller *webview1Controller = [[Webview1Controller alloc] initWithNibName:#"webview2" bundle:nil];
[self.navigationController pushViewController:webview1Controller animated:YES];
[webview1Controller.webview2 loadRequest:request];
[webview1Controller release];
return NO;
}
else {
return YES;
}
}
(Note, also, that UIViewController has a navigationController property so you can use that rather than getting it through your app delegate).
What happens if you load a copy of the request instead of the original, and then return NO?
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
myapp *delegate = [[UIApplication sharedApplication] delegate];
Webview1Controller *webview1Controller = [[Webview1Controller alloc] initWithNibName:#"webview2" bundle:nil];
//self.view = webview2;'
[delegate.navigationController pushViewController: webview1Controller animated:YES];
[webview1Controller.webview2 loadRequest:[[request copy] autorelease]];
[webview1Controller release];
return NO;
}