how to change WebView with buttons in separate View Controller - iphone

I need to change the URL of a WebView (located in WebViewViewController) using buttons in View Controller 1 (called PracticeViewController). I totally understand how to change the web View when it is in the same View Controller as the buttons, but I don't understand how to get the buttons to affect the WebView when the WebView is in a different ViewController than the buttons. Below is the code I currently have:
PracticeViewController.h
#import <UIKit/UIKit.h>
#interface PracticeViewController : UIViewController
- (IBAction)passGoogleButton:(id)sender;
- (IBAction)passYahooButton:(id)sender;
- (IBAction)passBingButton:(id)sender;
/* ok I tried to make this as clear as possible, and you can look at the other files if you don't understand what I mean, but at its core I want to change the web site loaded by the Web View by clicking on the buttons in the other View Controller */
#end
space (BTW is there an easier way to post on StackOverFlow Besides pressing space 4 times for every line of code? am I missing something?)
PracticeViewController.m
#import "PracticeViewController.h"
#import "WebViewViewController.h"
#interface PracticeViewController ()
#end
#implementation PracticeViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)passGoogleButton:(id)sender {
WebViewViewController.webSiteURL = #"http://www.google.com";
/* This supposedly works on a tutorial I saw, but Xcode flags it with the error 'Property webSiteURL not found on object of type 'WebViewViewController'' */
}
- (IBAction)passYahooButton:(id)sender {
WebViewViewController.webSiteURL = #"http://www.yahoo.com";
//same error as above
}
- (IBAction)passBingButton:(id)sender {
WebViewViewController.webSiteURL = #"http://www.bing.com";
//same error as above
}
#end
space
WebViewViewController.h
#import <UIKit/UIKit.h>
#interface WebViewViewController : UIViewController
{
UIWebView *myWebView;
NSString *webSiteURL;
}
#property (weak, nonatomic) IBOutlet UIWebView *myWebView;
#property (strong, nonatomic) NSString *webSiteURL;
/* I don't entirely understand what 'strong' means but I know it has to do with memory retention and that it (supposedly) should be used when I wan to transfer the value of the string 'webSiteURL' to the other ViewController */
#end
space
WebViewViewController.m
#import "WebViewViewController.h"
#interface WebViewViewController ()
#end
#implementation WebViewViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
[myWebView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:webSiteURL]]];
/* As you can see above, the WebView loads from the string 'webSiteURL' but I can't figure out how to assign different values to it based on what button is clicked in the other View Controller so that it will run in ' - (void)viewDidLoad.' I already know how to transfer the value of the string to other things within another view controller (like into a label or a text field) but what I really need to know is how to get the string 'webSiteURL' to change before the view is loaded */
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end

You have the right idea but you are missing a step here. You are never creating an instance of webViewController.
What you need somewhere is...
webViewcontroller *MyWebController = [[webViewController alloc] init];
It depends on how you are presenting the WebViewController. If you simply want the button to pop up the WebViewController modally you could use the following:
- (IBAction)passGoogleButton:(id)sender {
webViewController *myWebVC = [[webViewController alloc] init];
[myWebVC setWebSiteURL:#"http://www.google.com"];
[self presentViewController:myWebVC animated:YES completion:nil];
}
So, you can see here. You create the instance of the webViewController called myWebVC. Then you pass the string to it. So when myWebVC loads and it hits viewDidLoad, it will use the string that you passed in already and load the web view with that content. Hope that helps.
Also, Make sure you #synthesize your properties in your .m files.

You can use nsnotificationcenter to accomplish this task.
First register to notificationcenter in WebViewController, then send notification from another controller.
Here's a sample for registering to notificationcenter in WebViewController
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(nMessageOpenURL:) name:#"nMessageOpenURL" object:nil];
This is the code to run the logic when you receive the notification. (in WebViewController)
- (void)nMessageOpenURL:(NSNotification *)note {
//run the logic in here.
}
And finally this is the code where you trigger the notification.
[[NSNotificationCenter defaultCenter] postNotificationName:#"nMessageOpenURL" object:nil];
Here's the Apple documentation.

I got to know that you are trying to pass the value of the string of url between two view controllers but you are not getting it right!!
So if you are using storyboard you can try out passing this value using Segue. For Eg: you can use prepareForSegue to set the different values using if-else construct.
And if you are not using segue the best practice to pass those values will be using delegate.
Just create a delegate method and pass the url string as an argument.
Hope this works :)

Related

shouldStartLoadwithRequest not getting called in subclass

I have a view controlled app. On my xib I have no webviews but I do have buttons that bring up classes that have webviews. So hit button one and a uiwebview pops up so on and so forth.
Now in one of my classes I pull up a remote webpage that has a link on it. I want to over-ride that button link with shouldStartLoadwithrequest. How ever this never seems to get called.
Right now my class is called Tenth.m and I have this code in my view controller
- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType {
NSLog(#" Test spot 1");
NSString* scheme = [[request URL] scheme];
if ([#"didTap" isEqual:scheme]) {
// Call your method
NSLog(#" Test spot 2");
[self didTapButton1];
return NO;
} else {
NSLog(#" Test spot 3");
return YES;
}}
But I get nothing (none of my NSLogs). I have tried putting this into my Tenth.m class and still nothing. I have looked at other examples and even downloaded one but it only uses the viewcontroller and delegates classes. No third class.
I'm lost as to why its not getting called.
Here is my third class
#import "Tenth.h"
#implementation Tenth
- (void)awakeFromNib
{
[category10 loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://www.mywebsite.com/api/didtap.php"]]];
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)dealloc
{
[super dealloc];
}
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
/*
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView
{
}
*/
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return YES;
}
#end
remote page code
hello
Tenth.h file
#import <UIKit/UIKit.h>
#interface Tenth : UIViewController <UIWebViewDelegate> {
IBOutlet UIWebView *category10;
}
-(IBAction)back;
#end
My first guess is that the Web view does not have its delegate set. In order for it to call
- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType
The class containing this method needs to be set as the webview's delegate. So somewhere in the code there should be a line similar to webView.delegate = <variable>, where the variable is the instance of the class which has implemented the shouldStartLoadWithRequest: method.
This is often "self" when the webView is a subview of a viewController's view. But the way you have described your application, I am not sure if it will be self or not, but it sounds like it will not be self, but the name of the instance of a different class.
Maybe try this:
- (void)viewDidLoad
{
[super viewDidLoad];
// Remember to set web view delegate to self.
category10.delegate = self;
}

Objective-C on iPhone - tab bar crash

I'm relatively new to Objective-C and coding. I've tried doing a little dev on my own but have now become stuck on what is probably a rookie error.
I've created a tab bar controller with 5 views, one such view is a UIWebView. I've got the Webview working and it loads, but when I select a different tab, the app crashes. Please find my code below and any help would be appreciated!
#import <UIKit/UIKit.h>
#interface LiveViewController : UIViewController {
IBOutlet UIWebView *liveView;
}
#property (nonatomic, retain) UIWebView *liveView;
#end
#import "LiveViewController.h"
#implementation LiveViewController
#synthesize liveView;
// The designated initializer. Override if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
/*
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization.
}
return self;
}
*/
/*
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView {
}
*/
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[self.liveView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://www.britishseapower.co.uk/live/"]]];
[super viewDidLoad];
}
- (void)webViewDidStartLoad:(UIWebView *)liveView
{
// starting the load, show the activity indicator in the status bar
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
}
- (void)webViewDidFinishLoad:(UIWebView *)liveView
{
// finished loading, hide the activity indicator in the status bar
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
}
- (void)liveView:(UIWebView *)liveView didFailLoadWithError:(NSError *)error
{
// load error, hide the activity indicator in the status bar
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
// report the error inside the webview
NSString* errorString = [NSString stringWithFormat:
#"<html><center><font size=+5 color='red'>An error occurred:<br>%#</font></center></html>",
error.localizedDescription];
[self.liveView loadHTMLString:errorString baseURL:nil];
}
- (void)viewWillDisappear:(BOOL)animated
{
if ( [self.liveView loading] ) {
[self.liveView stopLoading];
}
self.liveView.delegate = nil; // disconnect the delegate as the webview is hidden
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
}
- (void)dealloc {
[liveView release];
[UIWebView release];
[LiveViewController release];
[super dealloc];
}
#end
Many thanks,
Ryan
[UIWebView release]; [LiveViewController release];
This is what make your app crash.
It's not valid to send a release message to a class itself.
What you've done with [liveView release]; is enough (with the call to [super dealloc];.)
You should also set the delegate to nil in the dealloc method as in the viewWillDisappear method self.liveView.delegate = nil;. This way you're sure to avoid any further message sent to the LiveViewController from the UIWebView.
You should read a bit more of documentation on Objective-C to better understand how it works.
Not sure if this is related but I noticed that you aren't setting yourself as the delegate anywhere in code which means that it must be connected in Interface Builder. Now when the view disappears, you are breaking that connection, but if the view were to re-appear and wasn't previously unloaded that connection will remain broken.
One of the most common reasons why an app may crash is to refer to or send a message to an object that has been already released from the memory. And this type of bug can be easily located using NSZombieEnabled and looking into the console message. So if you haven't already tried that, that's the first thing you must do.
The problem could be in LiveViewController but could be in the other view controllers as well. I wouldn't believe the problem is 100% in LiveViewController because the view controller wouldn't try releasing its view when the view is not shown unless it gets a memory warning. And you run the app using the simulator, it's unlikely it will have a memory warning unless you simulate one.
You would probably know that a view controller never create a view unless the view is used by an object. One of the other view controllers may have a silly bug in its view loading process which causes a crash. Or, you might have released another view controller by mistake. Make 100% sure that the other view controllers have no problem showing their views on their own, when you keep changing between their views (without showing LiveViewController).
So what I would do is to try NSZombieEnabled and check if it accesses a released object, and if it does, what the object is. Also, I will make a double check that the problem is related to LiveViewController. If it doesn't help I would log a message when LiveViewController and its liveView is deallocated (for liveView you need to subclass it). Because delegate property almost always does not retain an object, if the LiveViewController object is released (which shouldn't happen) and liveView still has a reference to it in the delegate property it will make a crash.
Crashes like this are almost always related to releasing an object that has already been released and deallocated.
Let XCode help you find the error. In XCode 4:
- In the toolbar, select the scheme list, and select 'Edit Scheme'
- Select the 'Run Your.app' in the list on the left.
- Under 'Environment Variables', add the following name/value pairs in the appropriate columns:
CFZombieLevel 3
NSZombieEnabled YES
Now when debug your app, you will get a message telling when -release is called on an object that already has a -retainCount of zero. Now you have a good clue to start your investigation.
Note that these flags prevent objects from being deallocated, so it is best to turn them on as needed to prevent out of memory errors.

How to create new view w/ webview from push of button

UPDATED QUESTION:
Hello , so I was able to create the modal view curl up overlay for this use. However I now have the issue that I can click on the button1 and pull up second view with the url1 on webView1, but when I click button2 I receive the display of url1 on webview also. below is the code can you help me out on what I'm doing wrong?
FourthViewController.h has the following code:
'
#import <UIKit/UIKit.h>
#interface FourthViewController : UIViewController {
UIButton *openBlogButton, *openFbButton, *openYelpButton;
}
#property (nonatomic, retain) IBOutlet UIButton *openBlogButton, *openFbButton, *openYelpButton;
-(IBAction)openBlog:(id)sender;
-(IBAction)openFacebook:(id)sender;
-(IBAction)openYelp:(id)sender;
#end
'
FourthViewController.m has the following code:
'
#import "FourthViewController.h"
#import "FourthBlogWebViewController.h"
#import "FourthFBWebViewController.h"
#implementation FourthViewController
#synthesize openBlogButton, openFbButton, openYelpButton;
-(IBAction)openBlog:(id)sender {
FourthBlogWebViewController *sampleView = [[[FourthBlogWebViewController alloc] init] autorelease];
[sampleView setModalTransitionStyle:UIModalTransitionStylePartialCurl];
[self presentModalViewController:sampleView animated:YES];
}
//THIS IS WHERE I THINK THE ISSUE IS, WHEN I CLICK openFacebook it should lead to the fb URL, it seems as if I should be able to list all possible urls on the first fourthwebviewcontroller, but i was not able to be successful so I tried making a second webview controller to feed it this url but this failed...lol. thnx for any input.
-(IBAction)openFacebook:(id)sender {
FourthFBWebViewController *sampleView = [[[FourthFBWebViewController alloc] init] autorelease];
[sampleView setModalTransitionStyle:UIModalTransitionStylePartialCurl];
[self presentModalViewController:sampleView animated:YES];
}
-(IBAction)openYelp {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"http://www.yelp.com"]];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (void)viewDidUnload {
[super viewDidUnload];
}
- (void)dealloc {
[openBlogButton release];
[openFbButton release];
[openYelpButton release];
[super dealloc];
}
#end
'
FourthBlogWevViewController.h
'
#import <UIKit/UIKit.h>
#interface FourthBlogWebViewController : UIViewController {
UIButton *dismissViewButton;
IBOutlet UIWebView *webViewFB;
}
#property (nonatomic, retain) IBOutlet UIButton *dismissViewButton;
#property (nonatomic, retain) UIWebView *webViewFB;
- (IBAction)dismissView:(id)sender;
#end'
FourthBlogWebViewController.m code:
'#import "FourthBlogWebViewController.h"
#implementation FourthBlogWebViewController
#synthesize dismissViewButton, webViewFB;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
}
return self;
}
-(IBAction)dismissView:(id)sender {
[self dismissModalViewControllerAnimated:YES];
}
- (void)viewDidLoad {
NSString *urlAddress = #"http://www.facebook.com";
NSURL *url = [NSURL URLWithString:urlAddress];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
[webViewFB loadRequest:requestObj];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (void)viewDidUnload {
[super viewDidUnload];
}
- (void)dealloc {
[dismissViewButton release];
[webViewFB release];
[super dealloc];
}
#end
Where or how would I add the second url and have it distinguis on click of other buttons. Thank you in advance for the ongoing help.
Original Question:
Hello,
So first app and I'm trying to make some basic function use of buttons, Im doing this in a tab bar application. On my fourth tab view a view opens with 3 buttons, on the click of the button I am trying to get a webpage to load within the app (i was able to successfully make the webpages open via safari on button touchup inside click, but that is not how I want it to load. So I edited the way it loads and on push of button the website is now opening within the webView. However I want to create this webview on a new view rather then on the same view where the 3 buttons are, but I'm not clear on how to do this. Any input would be greatly appreciated (I apologize beforehand since this seems as an easy task, but haven't figured it out yet, I did some searching before asking, but was unable to find anything that showed how to do this on push of different button to load webview on a new view within the same XIB.
Thanks.
Below is the code that I have for the load of webview on push of button.
On fourthviewcontroller.h
#import <UIKit/UIKit.h>
#interface FourthViewController : UIViewController {
IBOutlet UIWebView *webView;
}
-(IBAction)openWebsite:(id)sender;
-(IBAction)openButton2;
-(IBAction)openButton3;
#property (nonatomic, retain) UIWebView *webView;
#end
On fourthviewcontroller.m
#import "FourthViewController.h"
#implementation FourthViewController
#synthesize webView;
-(IBAction)openWebsite:(id)sender{
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://www.URL.com"]]];
}
-(IBAction)openButton2:(id)sender{
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://www.URL2.com"]]];
}
-(IBAction)openButton3:(id)sender{
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://www.URL3.com"]]];
}
Basically I'm trying to get different buttons to push to the same new view but the only difference is that i want the uiwebview to display a different URL depending on the button click that bring the new view.
As NWCoder mention, it depends how you like the new webview to be shown.
Display in UINavigationController-
Make your fourth tab a uinavigationcontroller and set the 3 button view controller as the top most view controller.
Create a new UIViewController that encapsulate the UIWebView.
When user click on the open webview button, create and push the uiviewcontroller that contains the uiwebview
Display in modal view:
Create a new UIViewController that encapsulate the UIWebView.
When user click on the open webview button, create and push the webview uiviewcontroller by calling the fourth's tab uiviewcontroller presentModalViewController:animated.

Unable to load view on button press iPhone

I am unable to load the next view on button press. I have created a button and attached the checkButtonPress action to the button in the IB. But when I press the button on the simulator the next view (ViewOne.xib) do not load. When I tried to debug the code; it is printing the NSLog(#"View One");written in the if statement below which means the code is reaching to that point but the next view is not loading. I have already created the ViewOne .h, .m .xib files. Following is the code written in check1ViewController.m implementation file:
#import "check1ViewController.h"
#import "ViewOne.h"
#implementation check1ViewController
-(IBAction) checkButtonPress: (id) sender{
int button = [sender tag];
if(button==1)
{
NSLog(#"View One");
ViewOne *tempObj = [[ViewOne alloc]initWithNibName:#"ViewOne" bundle:nil];
[self.navigationController pushViewController:tempObj animated:YES];
[tempObj release];
}
else if(button==2)
{
NSLog(#"View Two");
}
}
/*
// The designated initializer. Override to perform setup that is required before the view is loaded.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
// Custom initialization
}
return self;
}
*/
/*
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView {
}
*/
/*
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
}
*/
- (void)dealloc {
[super dealloc];
}
#end
The code is running fine with no errors or warnings.
Any suggestions if I am missing any part in the IB or in the code to be written or do need to override any method in any of the file ... or did I misplace IBAction before any other method
Sorry but I am new to iPhone dev so not sure what I did wrong ?
Thanks in advance
You application is not having navigation controller so add next view on window for this make object of AppDelegate class and then access window to addView.
YourAppDelegate *obj=(YourAppDelegate *)[[UIApplication sharedApplication] delegate];
[obj.window addSubView:viewController.view];

How to add a custom iPhone UI element that is not an IB component?

I'm trying to create an application that uses the iPhone MapView (under Google Code). I can't figure out how to integrate this thing into my application without handwriting the entire UI, ie not using the IB at all.
How can I use the Interface builder to create all of my menus and such but add the MapView in? Do I need to edit the MapView to make it an IB component?
Thanks!
EDIT:
#pgb
Here is my code, it still just displays a blank UIView, I have connected everything up on the IB side.
//
// NewTestViewController.h
// NewTest
//
#import <UIKit/UIKit.h>
#interface NewTestViewController : UIViewController {
UIView* mapPlaceholder;
}
#property (nonatomic, retain) IBOutlet UIView* mapPlaceholder;
#end
//
// NewTestViewController.m
// NewTest
//
#import "NewTestViewController.h"
#import "MapView.h"
#implementation NewTestViewController
#synthesize mapPlaceholder;
// The designated initializer. Override to perform setup that is required before the view is loaded.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
MapView *mapView = [[[MapView alloc] initWithFrame:
[[UIScreen mainScreen] applicationFrame]] autorelease];
[mapPlaceholder addSubview:mapView];
}
return self;
}
/*
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView {
}
*/
/*
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
}
*/
/*
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
*/
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[mapPlaceholder.subviews release];
[super dealloc];
}
#end
NEVERMIND FIGURED IT OUT THANGS PBG
You can probably create the whole interface in IB, add an empty UIView as the placeholder view, and then use addSubview: to add the MapView instance to the view hierarchy.
Your placeholder view can be defined as an IBOutlet, so you can then add the MapView from your UIViewController instance.
In IB you can add a UIView and then change the type of the view to any custom UIView - I'm assuming MapView subclasses UIView just as MKMapView does...
I'm trying to create an application that uses the iPhone MapView (under Google Code).
Why not use MapKit? Surely IB comes with an MKMapView in its Library.