Noob question fellas, but I cant get it.
I've got a View Controller that loads in a separate View Controller. I would like to be able on a button press to call a method inside the parent View controller. So here is what i've got
parent VC:
.h
-(void)callParentMethod;
.m
-(void)viewDidLoad{
self.childVC.parentVC = self;
}
-(void)callParentMethod{
NSLog(#"Hello?");
}
child VC:
.h
#import "TheParentViewController.h"
#property (nonatomic, weak) TheParentViewController *parentVC;
.m
-(void)addThis{
[self.parentVC callParentMethod];
}
I get no errors, the child VC method addThis seems to call the method, but the NSLog is never called. Any thoughts what i'm doing wrong?
I think parentVC releases because of weak reference. Try to use this method.
-(void)addThis{
NSLog(#"%#", self.parentVC);
[self.parentVC callParentMethod];
}
YourParentVC *parent = (YourParentVC*)[self presentingViewController];
parent.whatever = blah;
I am not quite sure what your application is, but you should not have to keep a reference to the parent view controller. A UIViewController already has a property called parentViewController which you can use in the following way:
[self.parentViewController methodToCall];
This will call a method on the parent view controller. You may need to cast the object in order to call custom methods
[(TheParentController *)self.parentViewController methodToCall];
This of course assumes that the child view controller's view is a subview of the parent view controller view. Hope this helps
Check whether your parent view controller is allocated.
parentnvc = [ParentViewController alloc]initWithNibName:#"somenib" bundle:nil];
if parentvc is allocated and initialised and call the method
You can create a property in child view controller say,
#class ParentVC;
#property(weak,nonatomic)ParentVC *parentVCreference;
and get the reference for the Parent view controller as follows
self.parentVCreference=(ParentVC*)self.parentViewController;
then you can call any exposed methods from ParentVC as follows
[self.parentVCreference parentVCMethod];
Note: You need to import header of ParentVC in ChildVC implementation file.
Related
How would I go about changing the a UILabel property in another view controller?
I have #import "SecondViewController.h" imported in the FirstViewController.m file and then
I have the following in a method in FirstViewController
-(IBAction) someAction {
SecondViewController *objV1 = [[SecondViewController alloc]init];
objV1.secondViewControllerLabel.alpha = 0.2;
NSLog(#"someAction");
}
when someAction is called nothing happens to the UILabel in the SecondViewController.
also, in this example both first and second view controllers are in another view controller called MainViewController. So, they are both onscreen at the same time.
thanks for any help.
From what you tell us, it would seem that you need to set the "embeded view controllers" as childs of the parent View Controller.
[mainViewController addChildViewController:childViewController];
[childViewController.view setFrame:self.view.bounds];
[self.childContainerView addSubview:childViewController.view];
[childViewController didMoveToParentViewController:self];
This is very powerful, because you can forward IBActions from the mainViewController to their child...
[mainViewController childViewControllers]
Returns an array of them, and also take a look at
– shouldAutomaticallyForwardRotationMethods
– shouldAutomaticallyForwardAppearanceMethods
So your child get automatically informed about the rotations of their parent.
To answer your question, you could do something like:
// In Parent View Controller
- (IBAction) anAction:(id) sender
{
for (CustomChildController *child in self.viewControllers) {
[child handleSomeAction];
}
}
Check out what the docs say for more details.
#Goles answer will work, but if you specifically want to trigger the change from FirstViewController.m you need to pass in a reference to SecondViewController somehow.
So you could do it with a custom init that takes a reference to your second viewcontroller as a parameter, or create a property on your FirstViewController that you can set from outside, which would be something like this:
FirstController.h:
#interface
..
#property (strong, nonatomic) UIViewController *second;
...
#end
FirstController.m:
#implementation
#synthesize second
In your parent ViewController you would create both the child view controllers, then:
ViewController1.second = ViewController2;
Then your action method would become:
-(IBAction) someAction {
self second.secondViewControllerLabel.alpha = 0.2;
NSLog(#"someAction");
}
Since in the secondViewController, secondViewControllerLabel has not been created yet, 'objV1.secondViewControllerLabel.alpha' will have no effect. Ideally, you should create a NSNumber property called labelAlpha in the secondViewController, set that property in the firstViewController, and then in the viewDidLoad of the second controller, add this line ::
self.secondViewControllerLabel.alpha = self.labelAlpha;
This will work for you.
I have a UIViewController in my IPhone application.For some animation i make a view like rootview with in that and added all the elements in that.When clicking on a button i removed that rootview and added another view controllers view.The problem is i was only loaded the view.I want to execute a function with in the new view controller.For that i need to set the first view controller as a delegate of the second view controller?can anybody help me ?
in secondVC, define something like the following:
#protocol secondVCDelegate
#interface secondVC : UIViewController
#property (nonatomic, assign) id<secondVCDelegate> delegate;
#end
#optional
-(void)someDelegateMethod:(secondVC*)viewController;
#end
at the time of creating the instance of secondVC you must assign the delegate property of secondVC to self! something like this:
// in firstVC
secondVC vc = [[secondVC alloc]...];
vc.delegate = self;
[navcontroller pushVC:vc];
the line vc.delegate = self; does the trick.
hope it helps...
Not sure from your typing that you want to call method of which controller from which controller?
Two scenarios:
A. In the first view controller you want to call a method of second view controller, use this:
[instantOfSecondViewController methodInSecondVC];
B. In the second view controller, you want to call a method of the first view controller. In this case you need to use The delegate pattern.
I have posted an example of both in this SO.
I have two view Controllers in my project ViewController, SettingsView. Here I am trying to update the ViewController's label, when i click on the SettingsView's back button. NSLog is working fine, but the label is not updating...
Please help me....
SettingsView.m
-(IBAction)backToMain:(id) sender {
//calling update function from ViewController
ViewController * vc = [[ViewController alloc]init];
[vc updateLabel];
[vc release];
//close the SettingsView
[self dismissModalViewControllerAnimated:YES];
}
ViewController.m
- (void)updateLabel
{
NSLog(#"Iam inside updateLabel");
self.myLabel.text = #"test";
}
Could you please tell me whats wrong with my code? Thank you!
You have to implement protocols for that. Follow this:
1) In SettingView.h define protocol like this
#protocol ViewControllerDelegate
-(void) updateLabel;
#end
2) Define property in .h class and synthesis in .m class..
#property (nonatomic, retain) id <ViewControllerDelegate> viewControllerDelegate;
3) In SettingsView.m IBAction
-(IBAction)backToMain:(id) sender
{
[viewControllerDelegate updateLabel];
}
4) In ViewController.h adopt protocol like this
#interface ViewController<ViewControllerDelegate>
5) In viewController.m include this line in viewDidLoad
settingView.viewControllerDelegate=self
Your label is not updating because , you are trying to call updateLabel method with a new instance.
You should call updateLabel of the original instance of viewcontroller from which you have presented your modal view.
you can use a delegate mechansim or NSNotification to do the same.
Delegate mechnaism would be clean. NSNotification is quick and dirty.
You are not exactly calling the correct vc. This is because you are creating a new instance of that class and calling the updateLabel of that instance.
You have a few options.
Either implement it as a delegate callBack (delegate messagePassing, or delegate notification - however you want to call it) to notify that class instance to call the updateLabel method.
Use the original instance VC as a dependency injection into the class that you are on right now, and use that instance to call the updateLabel
Use NSNotifications / NSUserDefaults to communicate between viewControllers and setup a notification system for your actions. This is quite easy, but not really great in the long run.
I would RECOMMEND option 1 (or) option 2.
Simply declare like this in SettingsView class:
UILabel *lblInSettings;// and synthesize it
Now assign like below when you presenting Settings viewController:
settingsVC.lblInSettings=self.myLabel;
Then whatever you update in lblInSettings it will be present in MainView obviously....
no need for any delegate methods or updating methods.
Means if you assign at the time of dismissing like
lblInSettings.text=#"My new value";
then self.myLabel also will be updated.
Let me know if you have any queries?
I have a viewcontroller and i am adding a subviewcontroller in that. Now i want to set value for a string from subviewcontroller which is in its superviewcontroller.
Please Suggest some idea
Thank You
if you want to access superview use the statement said by Jhaliya,
If you want to access superviewcontroller property frm subviewcontrller property ,
use
id mainViewController = [self.view.superview nextResponder];
here mainViewController is the superviewcontroller reference.
There a parentViewController property in UIViewController class reference,
This property is used for navigation, tab bar, and modal view controller hierarchies.
The above syntax is used for when you are setting a view as subview to a parentviewcontroller
You can access the super view controller using the parentViewController property on every UIViewController.
UIViewController *parent = self.parentViewController;
You can use superView method of UIView to access its parrent.
UIView *mySuperView = [MySubView superView];
use superview property of UIView.
UIMyView* mySuperView = (UIMyView*) myView.superview ;
mySuperView.mytextString = #"Assign string to super view";
EDITED:
You could get the list of all your UIViewController by using methods of UINaigationController .
Also current visible controller and top view controller,
Read the documentation for UINavigationController .
I have created a UITabBarController in my app delegate.
where each tab bar item holds a different UINavigationController that loads a custom UIViewController with a NIB (using -pushViewController:).
Inside one of the navigation controller, I load a custom UIView class with a custom NIB also.
This view is loaded multiple times inside the UIViewController.
The custom UIView has a UIButton, that on the event of touching it, I want to push a new UIViewController on the stack.
Problem is that I 'lost' the UINavigationController that holds the UIViewController.
I know I should use delegates, but haven't figured out who should which class should be the delegate.
Thanks in advance!
Neither .navigationController or .tabBarController will be available for a UIView or UIViewController that's been created but not pushed onto a stack
Either create a property on your View (or ViewController) class that is a UIViewController that is provided optionally after initialization or you could add a third argument to initWithNibName:bundle:
#interface CustomViewController : UIViewController
{
UIViewController *owner;
}
#property (nonatomic, assign) UIViewController* owner;
#end
Then in the owner ViewController:
CustomViewController *cvc = [[CustomViewController alloc] initWithNibNamed:nil bundle:nil];
cvc.owner = self;
It's too bad .parentViewController is read-only, this would be the sensible place for this.
You can get this using UIApplication class. Using this class you can find which viewController is placed at first. Here is the solution link for your problem.