will like to know how do i pass value back to the root view controller when i popToRoot.
introVideoViewController *intro = [introVideoViewController alloc];
intro.fromReset =1;
[self.navigationController popToRootViewControllerAnimated:NO];
With the VC that you want to pop back from, you need to give it a delegate property -
#class MyViewController;
#protocol MyViewControllerDelegate <NSObject>
-(void)myViewControllerDidDismiss:(MyViewController *)controller withSomeObject:(id)someObject;
#end
#interface MyViewController : UIViewController
#property (nonatomic, assign) id<MyViewControllerDelegate> myViewControllerDelegate;
#end
...and in the root VC you make it conform to that protocol, and implement the dismiss method -
-(void)myViewControllerDidDismiss:(MyViewController *)controller withSomeObject:(id)someObject {
// now I've got the object from the VC I just popped
}
Forgot to mention that you need to call myViewControllerDidDismiss:withSomeObject: when you pop the VC.
Edit - Also forgot to mention that you need to set the VC's delegate as your root VC when you create it, or else it'll be trying to call nil when you pop back -
[myViewController setMyViewControllerDelegate:self];
Just use the below code
NSArray *arr = [self.navigationController viewControllers];
CLASS_OF_ROOT_VIEW_CONTROLLER *rvc = (CLASS_OF_ROOT_VIEW_CONTROLLER *)[arr objectAtIndex:0];
rvc.variable = value;
Related
Currently I add a viewcontroller using pushViewController:animated: and now from within that new one would like to call a method inside my "parent"-controller. I think I get stuck at the navigationcontroller.
Currently trying this to see if it's the controller I want:
if([self.superclass isKindOfClass:[MySuperController class]])
// and tried:
if([self.presentingViewController isKindOfClass:[MySuperController class]])
None of these two worked.
How can I access the controller (a method in it) that pushed the current one?
Just like Marsson mentioned, you need to use delegate...
Here is an sample:
In your child view controller .h file:
#protocol ChildViewControllerDelegate <NSObject>
- (void)parentMethodThatChildCanCall;
#end
#interface ChildViewController : UIViewController
{
}
#property (assign) id <ChildViewControllerDelegate> delegate;
In your child view controller .m file:
#implementation ChildViewController
#synthesize delegate;
// to call parent method:
// [self.delegate parentMethodThatChildCanCall];
In parent view controller .h file:
#interface parentViewController <ChildViewControllerDelegate>
In parent view controller .m file:
//after create instant of your ChildViewController
childViewController.delegate = self;
- (void) parentMethodThatChildCanCall
{
//do thing
}
self.navigationController.viewControllers
Returns an array of all the view controllers in the navigation stack. The current view controller is at the top of the stack, the previous view controller is the next one down, and so forth.
So, you can do the following:
NSArray *viewControllers = self.navigationController.viewControllers;
int count = [viewControllers count];
id previousController = [viewControllers objectAtIndex:count - 2];
if ([previousController respondsToSelector:#selector(myMethod)])
[previousController myMethod];
If you know what class the previous controller is you can cast it explicity instead of using id.
Not sure of your application logic, but you can always do this.
In your "child" controller, declare property of type parent-controller. So, in your .h file:
MySuperController *superController;
property(nonatomic, retain)MysuperController *superController;
and in your .m file:
#synthesize superController;
Before "pushing" your child controller:
MyChildController *child = ...
[child setSuperController:self];
[self.navigationController pushViewController:child animated:YES];
Then in your child controller you can simply access your super with
[this.superController myMethod:param];
I'm not going to advocate this way of coding, but it's a quick/cheap/dirty way to accomplish things.
I want to return a NSString * from a UIViewController, called InputUIViewController, to the previous UIViewController, called CallerUIViewController, which started InputUIViewController. I want to do it just before or when InputUIViewController calls:
[self dismissModelViewControllerAnimated:YES];
Is there a standard way to do this?
The standard way to do this would be to use a delegate.
In your InputViewController add a new delegate protocal, and a property for your delegate.
Then in your CallerUIViewController implement the delegate. Then just before your dismiss the modal view controller you can call back to your delegate.
So your InputViewController might look like this:
#protocol InputViewControllerDelegate;
#interface InputViewControllerDelegate : UIViewController {
}
#property (nonatomic, assign) id <InputViewControllerDelegate> delegate;
#end
#protocol InputViewControllerDelegate
- (void)didFinishWithInputView:(NSString *)stringValue;
#end
The method that dismisses the modal view would look something like this:
-(void)dismissSelf
{
[self.delegate didFinishWithInputView:#"MY STRING VALUE"];
[self dismissModalViewControllerAnimated:YES];
}
Then in your CallerUIViewController you would implement the InputViewControllerDelegate and the didFinishWithInputView method.
The CallerUIViewController header would look something like:
#interface CallerUIViewController : UIViewController <InputViewControllerDelegate> {
}
and your didFinishWithInputView method would be implemented something like:
- (void)didFinishWithInputView:(NSString *)stringValue
{
// This method will be called by the InputViewController just before it is dismissed
}
Just before your present the InputViewController you would set the delegate to self.
-(void)showInputViewController
{
InputViewController *inputVC = [[InputViewController alloc] init];
inputVC.delegate = self;
[self presentModalViewController:inputVC animated:YES];
[inputVC release];
}
You can do this by simply creating a NSString object as property in prvious view controller and when in second view you call dismissModelViewControllerAnimated then before it assign value to previous view controller property. This might help you -
Passing data between classes using Objective-C
I'm a newbie in iPhone Programming. I'm trying to send a message from one view controller to another. The idea is that viewControllerA takes information from the user and sends it to viewControllerB. viewControllerB is then supposed to display the information in a label.
viewControllerA.h
#import <UIKit/UIKit.h>
#interface viewControllerA : UIViewController
{
int num;
}
-(IBAction)do;
#end
viewControllerA.m
#import "viewControllerA.h"
#import "viewControllerB.h"
#implementation viewControllerA
- (IBAction)do {
//initializing int for example
num = 2;
viewControllerB *viewB = [[viewControllerB alloc] init];
[viewB display:num];
[viewB release];
//viewA is presented as a ModalViewController, so it dismisses itself to return to the
//original view, i know it is not efficient
[self dismissModalViewControllerAnimated:YES];
}
- (void)dealloc {
[super dealloc];
}
#end
viewControllerB.h
#import <UIKit/UIKit.h>
#interface viewControllerB : UIViewController
{
IBOutlet UILabel *label;
}
- (IBAction)openA;
- (void)display:(NSInteger)myNum;
#end
viewControllerB.m
#import "viewControllerB.h"
#import "viewControllerA.h"
#implementation viewControllerB
- (IBAction)openA {
//presents viewControllerA when a button is pressed
viewControllerA *viewA = [[viewControllerA alloc] init];
[self presentModalViewController:viewA animated:YES];
}
- (void)display:(NSInteger)myNum {
NSLog(#"YES");
[label setText:[NSString stringWithFormat:#"%d", myNum]];
}
#end
YES is logged successfully, but the label's text does not change. I have made sure that
all of my connections in Interface Builder are correct, in fact there are other (IBAction)
methods in my program that change the text of this very label, and all of those other methods work perfectly...
Any ideas, guys? You don't need to give me a full solution, any bits of information will help. Thanks.
With
viewControllerB *viewB = [[viewControllerB alloc] init];
you are instantiating a new viewControllerB. This is not the viewControllerB that (I presume) you have in your nib file. You should make an outlet for that and wire it up.
Otherwise, possibly instantiate it with [... initWithNibName:] from a nib, instead of just [... init], and then (either way) push the instantiated view controller using [self.navigationController pushViewController:viewB animated:YES], or by presenting it modally as you seem to have mastered already.
As a sidenote, maybe name the viewcontroller variable viewConB, since there is a clear and important distinction between views and view controllers. Furthermore, class names tend to start with upper case, and variables with lower case, to keep things clear.
I'm using a NavigationController to "push" viewControllers from the rootView of an app.
I want to use delegates to comunicate the currently loaded view and the rootViewController. I was able to do this using NSNotificationCenter, but want give a try to delegates for this particular situation, since the communication is always going to be one-to-one.
In the view that is pushed, I declared the following delegate protocole in the header file:
#import <UIKit/UIKit.h>
#protocol AnotherViewControllerDelegate;
#interface AnotherViewController : UIViewController {
id <AnotherViewControllerDelegate> delegate;
}
- (IBAction) doAction;
#property (nonatomic, assign) id delegate;
#end
#protocol AnotherViewControllerDelegate <NSObject>
- (void) doDelegatedAction:(AnotherViewController *)controller;
#end
The doAction IBAction is connected to a UIButton in the view. In my implementation file, I added:
#import "AnotherViewController.h"
#implementation AnotherViewController
#synthesize delegate;
- (IBAction) doAction {
NSLog(#"doAction");
[self.delegate doDelegatedAction:self];
}
In my RootViewController.h I added AnotherViewControllerDelegate to the interface declaration:
#interface RootViewController : UIViewController <AnotherViewControllerDelegate> {...
and this to my implementation file
- (void) doDelegatedAction:(AnotherViewController *)controller {
NSLog(#"rootviewcontroller->doDelegatedAction");
}
Unfortunately it's not working. doDelegatedAction in the rootViewController is not been called. I suspect it's because of the way I push the AnotherViewController:
AnotherViewController *detailViewController = [[AnotherViewController alloc] initWithNibName:#"AnotherViewController" bundle:nil];
[self.navigationController pushViewController:detailViewController animated:YES];
[detailViewController release];
Should I tell, in any way, to AnotherViewController that its delegate is going to be RootViewController just in the moment it's been pushed? or am I missing something else?
You need to set the delegate of AnotherViewController to the rootViewController in order for everything to be connected up properly.
If you are initializing AnotherViewController in your rootViewController it would be:
AnotherViewController *detailViewController = [[AnotherViewController alloc] initWithNibName:#"AnotherViewController" bundle:nil];
detailViewController.delegate = self;
[self.navigationController pushViewController:detailViewController animated:YES];
Basically I have a viewController that loads at app startup. In that VC, depending on whether there is userdata, I serve up a ModalView with either a login. After the user logs in, I can then dismiss the modalView, but I would like to call a method on the opener that will then populate a table with data.
I thought from the modalView I could do something like
[self.parentViewController loadInitialData];
[self.dismissModalViewControllerAnimated:YES];
but that does not work..
any suggestions?
The problem is because self.parentViewController is of type "UIViewController" and your -loadInitialData method doesn't exist in UIViewController. There are a couple of common ways to solve this problem... from easiest and least "correct" to most complicated and most "correct":
1) First you need to cast your self.parentViewController to the type of your parent view controller. Something like:
MyParentViewController *parentVC = (MyParentViewController*)self.parentViewController;
[parentVC loadInitialData];
2) You can add a property to your modal view controller that explicitly keeps a reference to your parent view controller and then call loadInitialData doing that.
#interface MyModalViewController : UIViewController {
MyParentViewController *myParentViewController;
}
#property (nonatomic, retain) MyParentViewController *myParentViewController;
Then you can call:
[self.myParentViewController loadInitialData];
3) The most complicated, but most correct way to do it is to create a Delegate protocol, have your ParentViewController implement the protocol and have your modal view controller keep a reference to the delegate and call that way. Something like:
#protocol ManageDataDelegate
- (void) loadInitialData;
#end
#interface MyParentViewController : UIViewController <ManageDataDelegate> { ...
#interface MyModalViewController : UIViewController {
id<ManageDataDelegate> delegate;
}
#property (nonatomic, assign) id<ManageDataDelegate> delegate;
When you present your modal view controller, just set the delegate. In your MyParentViewController:
MyModalViewController *vc = [[MyModalViewController alloc] init];
vc.delegate = self;
[self presentModalViewController:vc];
Then in your modal view controller you can call back like so:
[self.delegate loadInitialData];