I have a small doubt. I have a NSObject class where I am trying to display an alert view. So after the alert view is displayed when I tap on OK button I want to push a navigation controller onto the stack. Can I push a navigation controller from general NSObject class? Please let me know guys..thanks for your time..
This is the code..
- (void) alertView:(UIAlertView *)alert clickedButtonAtIndex:(NSInteger)buttonIndex{
SettingsViewController *homeView = [[SettingsViewController alloc] initWithNibName:#"SettingsViewController" bundle:nil];
[self.navigationController pushViewController:homeView animated:NO];
[homeView release];
}
I am creating a property called navigationController of type UINavigationController and when I catch the error I am displaying an alert view and I am using above method to push the view controller but it doesn't work..
Yes and no... depending on how you have your application set up. To push views onto the navigation stack you need to have a navigation controller.
Does your NSObject have access to this navigation controller - you might have to set up a delegate method that gets called from your delegate view when the alert view delegate gets called in your NSObject.
I'm just wondering why you're displaying a UIAlertView in an NSObject, why aren't you displaying it in a UIView or a UIViewController?
CustomObject.h
#protocol CustomObjectDelegate<NSObject>
#optional
- (void)customObjectAlertViewDidClickOk;
#end
#interface CustomObject : NSObject <UIAlertViewDelegate>{
id<CustomObjectDelegate> delegate;
}
#property (nonatomic, assign) id<CustomObjectDelegate> delegate;
#end;
CustomObject.m
#synthesize delegate;
// then put this:
- (void)alertView:(UIAlertView *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
[delegate customObjectAlertViewDidClickOk];
}
Then your ViewController .h file needs to include the custom object and assign the delegate methods:
#include "CustomObject.h"
#interface MyViewController : UIViewController <CustomObjectDelegate> {
}
#end
and the .m viewDidLoad (or similar):
- (void)viewDidLoad{
CustomObject *obj = [[CustomObject alloc] init];
[obj setDelegate:self];
}
- (void)customObjectAlertViewDidClickOk{
AnotherViewController *page = [[AnotherViewController alloc] initWithNibName:nil bundles:nil];
[self.navigationController pushViewController:page];
}
Thats how I would do it - given I'm not too sure i understand quite what you're asking. :) thats all off the top of my head as well - so don't take it letter for letter, but you have the basis there to start off with. You can build on it. Look up #protocols and delegate methods, its all in there. :)
Related
I have 2 ViewControllers, in 1st - TableView and in 2nd - button with label on it. When I click on the button in 2nd ViewController I need to go back on TableView and set in
cell.detailTextLabel.text
text from label on the button.
For go back to first view I use:
[self.navigationController popToViewController:[self.navigationController.viewControllers objectAtIndex:1] animated:YES];
but how I can set label from second view to:
cell.detailTextLabel.text
in first view?????
I would define a protocol & delegate in the second view controller
#protocol SecondViewController;
#interface SecondViewController : UIViewController
#property (nonatomic, assign) id<SecondViewController> delegate;
#end
#protocol SecondViewController <NSObject>
- (void)secondViewController:(SecondViewController *)controller didTappedOnButton:(UIButton *)button;
#end
then when the button is tapped call the delegate:
- (IBAction)buttonTapped:(UIButton *)sender
{
// do somthing..
// then tell the delegate about the button tapped
[self.delegate secondViewController:self didTappedOnButton:sender];
}
In your first view controller implement the protocol
#interface FirstViewController : UIViewController <SecondViewControllerDelegate>
when you push the second view controller, set the first as the second delegate:
- (void)someMethodThatPushTheSecondViewController
{
SecondViewController *svc = [[SecondViewController alloc] init];
[self.navigationController pushViewController:svc animated:YES];
svc.delegate = self;
}
And implement the delegate method to get notified when the button tapped
- (void)secondViewController:(SecondViewController *)controller didTappedOnButton:(UIButton *)button
{
// do somthing after button tapped
// you can get the button title from button.titleLabel.text
}
To access a parent class method or property you gotta implement a protocol, and use it's delegates. You can access child class methods/properties using it's class object that you create in the current (parent) class. But how you want to access a parent class entity from a child class? YES, implementing protocols.
Or the newbie way: after tapping your button, save the needed value into NSUserDefaults. Then, when you go to your parent class (viewController 1), ion viewWillAppear, check that saved value, and if it's not nil, display it.
[self.navigationController popViewControllerAnimated:YES];
I've been struggling with this problem for some days. I've been trying to have a persistent RightBarButtonItem in several views. By researching on several blogs and web searches, it turned out that I need to set my rightBarButtonItem in the function -navigationController:willShowViewController:animated:.
My app does not show any errors but when I try to debug or use NSLog statements, it shows that the app does not enter this function at all. I have <UINavigationControllerDelegate> in the interface of my RootViewController class, but I also set my NSXMLParser parser as a delegate to itself ([parser setDelegate:self];) in another class. Can this be a problem that the navigationController delegate is not recognized or something.
- (void)navigationController:(UINavigationController *)navigationController
willShowViewController:(UIViewController *)viewController
animated:(BOOL)animated
{
//[self.navigationController.navigationItem setRightBarButtonItem:twoButtons animated:YES];
self.navigationItem.rightBarButtonItem = twoButtons;
NSLog(#"We are in navigationController delegate function");
}
If you want several views to have the same rightBarButtonItem, why not create a base UIViewController that all of your views inherit? Conceptually, I think this is a better solution because not only will all of the views inherit the button, they'll get the behavior as well ;) This also allows you to override methods in your base controller just in the event that one view needs to handle a click in a slightly different manner.
#interface BaseViewController : UIViewController
#property (nonatomic, retain) YourApplicationDelegate *delegate;
- (void) setupButtons;
- (void) buttonClicked:(id)sender;
#end
#import "BaseViewController.h"
#implementation BaseViewController
#synthesize delegate=_delegate;
- (void) viewDidLoad {
[super viewDidLoad];
self.delegate = (YourApplicationDelegate *) [[UIApplication sharedApplication] delegate];
[self setupButtons];
}
- (void) setupButtons {
UIBarButtonItem *button = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSave
target:self
action:#selector(buttonClicked:)];
self.navigationItem.rightBarButtonItem = button;
[button release];
}
- (void) buttonClicked:(id)sender {
NSLog(#"Click!");
}
- (void) dealloc {
[_delegate release];
[super dealloc];
}
#end
/* Now the rest of your view controllers look pretty clean and you don't have a lot of
code in your delegate method. Most problems can be solved with a layer or two of abstraction :) */
#interface MyViewController : BaseViewController
#end
Base ViewControllers are also a good place to inject your application delegate which you'll need a lot. That's why I included it in the code block even though it wasn't part of your question. If you wanted to use a shared instance of a button or delegate the response handler out then you can easily put that code in your delegate and leverage a base view to access it easily.
I have a view whose controller is being instantiated (NSLog says so), but the view doesn't show up. If I load it as a modal view it appears, but not if I allocate it.
I have this structure (MenuView is the view that doesn't appear):
// ViewController.h
#import "MenuViewController.h"
#class MenuViewController;
#interface ViewController : UIViewController<ASIHTTPRequestDelegate>{
...
IBOutlet MenuViewController *menuView;
}
...
#property(nonatomic, retain) MenuViewController *menuView;
#end
// ViewController.m
#import "MenuViewController.h"
#implementation ViewController
#synthesize menuView;
- (void)loadMenu{
// THIS WORKS
// [self presentModalViewController:menuView animated:YES];
// THIS DOESN'T (VIEWCONTROLLER IS INSTANTIATED BUT VIEW DOESN'T APPEAR
menuView = [[[MenuViewController alloc] initWithNibName:#"MenuView" bundle:Nil] autorelease];
[self.navigationController pushViewController:menuView animated:YES];
}
Some ideas:
Try using self.menuView when assigning:
self.menuView = [[MenuViewController alloc] initWithNibName:#"MenuView" bundle:Nil];
Also, probably shouldn't autorelease a property. Release it in dealloc and set it to nil in viewDidUnload.
Make sure that self (ViewController) has a navigationController. Was ViewController pushed/presented by a navigationController?
Is - (void)loadMenu{ being called from the MainThread? Check with [NSThread mainThread]
Check out some tutorials/examples:
Adding a Navigation Controller by Hand
NavigationController Application in iPhone
Tutorial: Introducing UINavigationController Part 1
iPhone View Switching Tutorial
I have a UIViewController which shows different UIViewController sub-classes. In the main UIViewController.m, I have a sub-class called 'Home' load on app start.
Now, which the Home view loaded, I have a button which I want to use to switch to another view called 'PreGameInfo'. I'm trying to use the code below:
- (IBAction)showPreGameInfo:(id)sender {
[self.view insertSubview:preGameInfo.view atIndex:0];
}
It doesn't work, and I know it's because the 'self.view' needs to refer to the main UIViewController rather than the self of the 'Home' view. Does anyone know how to insertSubView to the main UIViewController when using a UIButton whilst in a SubView???
Thank you!
You can use a delagate. It very easy
So implement this in your information view controller;
In the InformationViewController.h
#protocol InformationViewControllerDelegate;
#interface InformationViewController : UIViewController {
id <InformationViewControllerDelegate> delegate;
}
#property (nonatomic, assign) id <InformationViewControllerDelegate> delegate;
- (IBAction)returnBack:(id)sender;
#end
#protocol InformationViewControllerDelegate
- (void)InformationViewControllerDidFinish:(InformationViewController *)controller;
#end
in the InformationViewController.m
- (IBAction)returnBack:(id)sender {
[self.delegate InformationViewControllerDidFinish:self];
}
And use the delegate in any view controller you need it like this :
In the HomeViewController.h
#import "InformationViewController.h"
#interface HomeViewController : UIViewController <InformationViewControllerDelegate> {
}
Write the method to change the view from Home view to Information view
- (IBAction)goToInformationView:(id)sender;
In the HomeViewController.m
- (IBAction)goToInformationView:(id)sender {
InformationViewController *controller = [[InformationViewController alloc] initWithNibName:nil bundle:nil];
controller.delegate = self;
// You can chose the transition you want here (they are 4 see UIModalTransitionStyle)
controller.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:controller animated:YES];
[controller release];
}
And the last but not least the delegate method it inform the HomeViewController when the InformationViewController had finished
- (void)InformationViewControllerDidFinish:(InformationViewController *)controller {
[self dismissModalViewControllerAnimated:YES];
}
I hope it helps
- (IBAction)showPreGameInfo:(id)sender {
[superview insertSubview:preGameInfo.view atIndex:0];
}
Does this code work?
[self.parentViewController.view addSubview:myView];
Just do it in the modalView:
[self presentModalViewController:preGameInfo animated:YES]
or you can do something like this...
This line will add your new view to windows rootViewControllers view
[self.view.window.rootViewController.view addSubview:preGameInfo.view];
I have an app with tabbar and webview. I'm trying to make the app come back to default url each time user taps the bar. Right now I'm intercepting taps and launching a method, however it's not affecting my webview (it's not loading the page). The method works properly when called from the class, but not when it's called from my app delegate, where I'm intercepting taps.
I suspect it's something with the way I create the SecondViewController object that it's not pointing to the webview, but I have no clue what I'm doing wrong.
Here is the code:
Second view header (where the WebView is located)
#interface SecondViewController : UIViewController {
IBOutlet UIWebView *secondView;
}
- (void) goToPage;
Second view implementation
#import "SecondViewController.h"
#implementation SecondViewController
- (void)awakeFromNib
{
[self goToPage];
}
- (void) goToPage
{
NSLog(#"go to page");
NSString *newURL = [NSString stringWithFormat:#"http://pageurl"];
[secondView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:newURL]]];
}
My app delegate, where I call the SecondViewController class method:
#import "RedDragonAppDelegate.h"
#import "SecondViewController.h"
#implementation RedDragonAppDelegate
#synthesize window;
#synthesize rootController;
- (void)applicationDidFinishLaunching:(UIApplication *)application {
// Override point for customization after application launch
[window addSubview:rootController.view];
}
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
NSLog(#"didSelectViewController %d", rootController.selectedIndex);
SecondViewController * sv = [[SecondViewController alloc] init];
if (rootController.selectedIndex == 0){
//NSLog(#"if in didSelectViewController 0");
} else if (rootController.selectedIndex == 1) {
//NSLog(#"if in didSelectViewController 1");
[sv goToPage];
}
}
Thanks fot your help!
If I understand correctly, you've got an instance of SecondViewController with secondView connected to an instance of UIWebView in Interface Builder. What you want to do is call goToPage on that instance of SecondViewController from RedDragonAppDelegate. (In particular, note that I'm talking about instances of these--I believe this is the underlying issue.)
In tabBarController:didSelectViewController:, when you do SecondViewController * sv = [[SecondViewController alloc] init];, you are creating a new instance of SecondViewController and you can call its goToPage method, but sv is not the same instance of SecondViewController that appears in Interface Builder and has secondView connected to the UIWebView (that is, when you create a new instance of SecondViewController, the ivar secondView is unset and seems to be nil, but I don't know that it's guaranteed to be nil).
What you probably(*) want to do is add IBOutlet SecondViewController *sv; to the #interface of RedDragonAppDelegate, make sure that you have an instance of RedDragonAppDelegate in Interface Builder, connect the new IBOutlet sv of RedDragonAppDelegate to the instance of SecondViewController in Interface Builder, and delete the line in tabBarController:didSelectViewController: that defines and initializes sv.
(*) I'm not 100% certain on this because I don't do iPhone stuff and I don't know how your various views/objects/etc. are arranged in XIB/NIB files, but if everything's in one XIB/NIB file, I'm pretty sure it'll work.