I have a navigation-based application with 2 UIViewControllers (controller-2 is pushed onto controller-1 when the user selects a particular row within a UITableView displayed using controller-1).
Here's the 'twist'… When controller-1 is loaded, I want to "prefetch" a URL containing HTML/javascript into a UIWebView. Initially, the user won't see this UIWebView. Instead they will see a UITableView allowing them to click on 5 different options (row0, row1, row2, row3, row4).
When the user selects a row I would like to push a new view onto the stack and "pass" the HTML/Javascript to a UIWebView located within this new view, and display the web-page in the new view.
Is it possible to pass the UIWebView like this?
I've tried the following, which is not displaying the HTML within UIWebView, so any suggestions on how to pass the UIWebView (or alternatives) would be great. I'm pretty sure I've made the correct connections within my nib file for controller2.
To explain my motives. I want to use javascript to hide certain elements of the web-page depending on which row the user clicks. To me, it's faster and easier to make 1 URL request and then use javascript to hide various HTML elements than it is to make 5 different URL requests, fetching 5 separate web-pages. So, if there are alternative thoughts to this approach, that would be great, too. I thought about doing this all within 1 viewcontroller (adding and removing subviews), but I'd rather push onto a new view to take advantage of the navigation controller.
TYVM!!!!
////////// controller 1 //////////////////////
- (void)viewWillAppear:(BOOL)animated {
// do other stuff ///
NSURLRequest *request_object = [NSURLRequest requestWithURL:self.url];
[self.web_view1 loadRequest:request_object];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
self.view_controller2 = [[[ViewController2 alloc] initWithNibName:#"ViewController2" bundle:nil] autorelease];
self.view_controller2.web_view2 = self.web_view1;
[self.navigationController pushViewController:self.view_controller2 animated:YES];
}
//////////// controller 1 //////////////////////
//
///////////// portion of controller 2 header file /////////////////////////
#interface ViewController2 : UIViewController {
IBOutlet UIWebView *web_view2;
}
#property (nonatomic, retain) IBOutlet UIWebView *web_view2;
//////////// portion of controller 2 implementation file //////////////
#import "ViewController2.h"
#implementation ViewController2
#synthesize web_view2;
- (void)dealloc {
[web_view2 release], web_view2 = nil;
[super dealloc];
}
//////////// controller 2 //////////////////////////
You've got the right idea, but you need to do one other thing. In your -tableView:didSelectRowAtIndexPath:. you need to add the webview to the viewController's view, not just assign it to an outlet. The following might work, depending on your XIB files:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
self.view_controller2 = [[[ViewController2 alloc] initWithNibName:#"ViewController2" bundle:nil] autorelease];
self.web_view1.frame = self.view_controller2.web_view2.frame;
[self.view_controller2.web_view2 removeFromSuperview];
self.view_controller2.web_view2 = self.web_view1;
[self.view_controller2.view addSubview: self.web_view1];
[self.navigationController pushViewController:self.view_controller2 animated:YES];
}
This assumes that web_view2 is a valid and hooked up outlet, containing a webview in the location you want your 'cached' view to be.
Related
I have application
I want a button to open another screen with done button
after click this button a data be transfered from the current screen to the previous one
like opening options screen , how to let the main view know the changes be done on this subview
Best regards
You can use properties for this.
Create a property in the second class: .h file
#interface DetailViewController : UIViewController {
NSString *head;
}
#property(nonatomic,retain)NSString *head;
#end
in .m file
#synthesize head;
Now in your firstviewcontroller or first class
if (dt==nil) {
DetailViewController *d = [[DetailViewController alloc]initWithNibName:#"Detailview" bundle:nil];
self.dt = d;
[d release];
}
dt.head=itemsum;
[self.navigationController pushViewController:self.dt animated:YES];
Suppose you have to pass NSString to other class then declare one Nsstring in second class and make accessor method for nsstring and then call this code from first view controller
yournextviewcontroller *viewcontroller = [[yournextviewcontroller alloc] initWithNibName:#"yournextviewcontroller" bundle:nil];
viewcontroller.Stringname = name;
[self.navigationController viewcontroller:evernotebook animated:YES];
You can take UIView as IBOutlet in the same ViewController. Show that view with click on Button like
IBOutlet UIView *yourAnotherScreenView; //Bind this to your view in XIB file.
[self.view addSubView:yourAnotherScreenView];
[self.view bringSubViewtoFront:yourAnotherScreenView];
Take Done button on the view and wireup the action event in the same controller and do the necessary stuff as required.
Use the simple delegate concept of Objective-C .
Check very simple answers in the below post for using delegate in Objective-C .
How do I set up a simple delegate to communicate between two view controllers?
I am parsing RSS feeds and loading results into a table. When the user clicks on a story, they are taken to the web page.
At the moment I am using:
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:story]];
Trouble is that this launches Safari and closes my app.
Is there a way to open the webpage in my app so to speak? I'd like the webpage to appear with a "Done" button that closes the web page and returns the user back to the table.
Any help (and code examples) are much appreciated.
You can use UIWebView in a new view controller launched via navigationController pushViewController selector, and have a toolbar item to "View in Safari" which will launch full Safari browser (and putting your app in the background/terminating).
Some example code snippets:
Assumptions:
(1) You have a view controller entitled: WebViewController (with same .xib) file.
(2) This view controller has a UIView which is subview of the main view;
#interface WebViewController: UIViewController <UIWebViewDelegate> {
UIWebView *webview;
NSString *someUrlToLoad;
}
#property (nonatomic, retain) IBOutlet UIWebView *webview;
#property (nonatomic, copy) NSString *someUrlToLoad;
In this view controller's viewDidLoad method:
-(void) viewDidLoad {
[super viewDidLoad];
[webview loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:self.someUrlToLoad]]];
}
You load this controller when someone clicked on the cell in your tableview:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
WebViewController *viewController = [[WebViewController alloc] initWithNibName:#"WebViewController" bundle:nil];
viewController.someUrlToLoad = <url for this cell>;
[self.navigationController pushViewController:viewController animated:YES];
[viewController release];
}
Most likely you will want to include some hook into the UIWebViewDelegate to stop/show an activity indicator in the navigation bar so the user is aware that something is happening while the page loads.
As the title says none of my tableview controller methods are being called.
The steps I went through to create my table view are as follows.
1) I created a new file based on UITableViewController and selected the create with xib option. I Named my file myStuffViewController.
2) I have a rootview controller which is a UIViewController. In this view I have a navigation controller that I want to push my tableview controller onto at a certain point.
3) I setup my tableview and nav controller like so
mystuff = [[MyStuffViewController alloc]initWithNibName:#"MyStuffViewController"bundle:[NSBundle mainBundle]];
accountView = [[AccountView alloc] initWithNibName:#"Login" bundle:[NSBundle mainBundle]];
accountViewNavController = [[UINavigationController alloc] init];
accountViewNavController.delegate = self;
NSArray *ar= [NSArray arrayWithObjects:accountView,mystuff, nil];
[accountViewNavController setViewControllers:ar animated:NO];
[accountViewNavController popToRootViewControllerAnimated:NO];
accountView.title=#"Login";
4) Then when a user pushes a button I want to push the table view controller onto the stack like this.
[accountViewNavController pushViewController:mystuff animated:YES];
I've even tried calling [self.tableView reloadData] but none of the methods get called.
Could somebody propose why my table view methods are not being called?
EDIT 1
Just so I'm being as clear as I can be here is what my header file looks like. To be it doesnt seems like I'm missing anything.
#interface MyStuffViewController : UITableViewController<UITableViewDataSource,UITableViewDelegate> {
RemixView *remixView;
NSMutableArray *remixListArray;
TBXML*tbxml;
}
#property(nonatomic,retain)NSMutableArray *remixListArray;
#property(nonatomic,retain)RemixView *remixView;
#property(nonatomic ,retain)TBXML *tbxml;
-(void)fetchRemixList:(NSString *)uid key:(NSString *)k1;
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath;
#end
Check
You declare in the .h file that you implement the two table view delegates UITableViewDelegate & UITableViewDatasource
In the NIB make sure you link to your delegate in file owner OR if you have created the TableView programmatically make sure you set the delegate ivar also.
Then see if the delegate methods start getting called
I am doing a book kinda application using a viewBased application. The mainView acts as the backgroundView for loading pages. Each page is a different view and have its own nib. When i swipe on a page(actually on the mainView which have loaded the current view/page), that page will be removed and the next/previous page will be added.
[currentPage.view removeFromSuperview];
[self.view insertSubview:nextPage.view atIndex:0];
I have added a popoverController with a barbutton in this mainView. Its intialized with a tableviewController class named popClass. PopClass is another UITableViewController class which will act as the parent for the popViewController.
self.myPopController = [[PopController alloc] initWithStyle:UITableViewStylePlain];
self.myPopOverController = [[UIPopoverController alloc] initWithContentViewController:myPopController];
When I select certain row in the popover, I want the backgroundview(mainView) to load the page corresponding to the number of the row.
For that I have written a function in bookView(mainView) Controller class. And is calling it from the popOver's parent class when i select certain row.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSInteger toPageNumber = indexPath.row + 1;
[viewController changeToPage:toPageNumber];
}
Function and the lines of code are executing but nothing is happening. Even the log lines are printed but no action takes place. The code is the same for removing a page and adding another page which is working successfully when i swipe the view/page.
What is the problem? OR is there anyother way to make the view change in mainView by using the popover?
You need to have refernce of the background view controller in the popover controller.
In the PopController controller you should have a delagate like:
#interface PopController: UITablViewController{
//// other varibales;
id delegate;
}
#property (nonatomic, retain) id delgate;
Now from the class in which you are showing the popovercontroller
you should add this line:
[myPopController setDelegate:self];
Then you can easily acces any method of the main view controller class. By using
[delegate callTheRequiredMethod];
Hope this helps.
Thanks,
Madhup
It's hard to tell what's going wrong without looking at the code. That said, here's what I'd do:
(1) When a row is selected in mainView, present the popoverController modally:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
PopoverViewController *vc = [[PopoverViewController alloc] init];
[self.navigationController presentModalViewController:vc animated:YES];
[vc release];
}
(2) When something changes in the popoverController, for example a row is selected, set a value in the parentViewController (which should be the MainView):
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
self.parentViewController.value = someValue;
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
(3) Dismiss the popoverController where-ever you choose by calling:
[self dismissModalViewControllerAnimated:YES]`
I need to pop up a quick dialog for the user to select one option in a UITableView from a list of roughly 2-5 items. Dialog will be modal and only take up about 1/2 of screen. I go back and forth between how to handle this. Should I subclass UIView and make it a UITableViewDelegate & DataSource?
I'd also prefer to lay out this view in IB. So to display I'd do something like this from my view controller (assume I have a property in my view controller for DialogView *myDialog;)
NSArray* nibViews = [[NSBundle mainBundle] loadNibNamed:#"DialogView" owner:myDialog options:nil];
myDialog = [nibViews objectAtIndex:0];
[self.view addSubview:myDialog];
problem is i'm trying to pass owner:myDialog which is nil as it hasn't been instantiated...i could pass owner:self but that would make my view controller the File's Owner and that's not how that dialog view is wired in IB.
So that leads me to think this dialog wants to be another full blown UIViewController... But, from all I've read you should only have ONE UIViewController per screen so this confuses me because I could benefit from viewDidLoad, etc. that come along with view controllers...
Can someone please straighten this out for me?
There is no such thing as a view controller being on the screen; its view is on the screen. With that said, you can present as many views as you want on the screen at once.
I would create a new view and view controller. You would not make a UIView be a UITableViewDelegate, you make a UIViewController be a UITableViewDelegate. But instead of doing that manually, instead make your new view controller a subclass of UITableViewController, if you're using iPhone OS 3.x+. You can then present this view controller modally.
You probably want to give the user a chance to cancel out of the selection. A good way to do that is to wrap your new dialog view controller in a UINavigationController and then put a "Cancel" button in the nav bar. Then use the delegate pattern to inform the parent view controller that the user has made their choice so you can pop the stack.
Here's what the code will look like inside your parent view controller, when you want to present this option dialog:
- (void)showOptionView
{
OptionViewController* optionViewController = [[OptionViewController alloc] initWithNibName:#"OptionView" bundle:nil];
optionViewController.delegate = self;
UINavigationController* navController = [[UINavigationController alloc] initWithRootViewController:optionViewController];
[self.navigationController presentModalViewController:navController animated:YES];
[navController release];
[optionViewController release];
}
Your OptionViewController .h will look like this:
#protocol OptionViewControllerDelegate;
#interface OptionViewController : UITableViewController
{
id<OptionViewControllerDelegate> delegate;
}
#property (nonatomic, assign) id<OptionViewControllerDelegate> delegate;
#end
#protocol OptionViewControllerDelegate <NSObject>
- (void)OptionViewController:(OptionViewController*)OptionViewController didFinishWithSelection:(NSString*)selection;
// or maybe
- (void)OptionViewController:(OptionViewController*)OptionViewController didFinishWithSelection:(NSUInteger)selection;
// etc.
#end
Your OptionViewController.m will have something like this:
- (void)madeSelection:(NSUInteger)selection
{
[delegate OptionViewController:self didFinishWithSelection:selection];
}
Which has a matching method back in your original view controller like:
- (void)OptionViewController:(OptionViewController*)OptionViewController didFinishWithSelection:(NSUInteger)selection
{
// Do something with selection here
[self.navigationController dismissModalViewControllerAnimated:YES];
}
There are plenty of examples throughout Apple's sample source code that follow this general pattern.