I would like to use a method in a viewcontroller that is the "container" of an other viewcontroller but not directly the parent. I display a popover containing a custom xib file. For that I have three viewcontrollers:
1) popoverVC managing the settings of the popover (like alpha value, any arrow, size, and the method I want to use from "outside" dismisspopover)
2) customVC with a xib file to change the content of my popover (some text and some buttons).
3) mainVC from where the popover is launched and where I receive some actions when interacting with my buttons in customVC. mainVC is the delegate of customVC.
My problem is I don't know of to call dismisspopover method in popoverVC from an action in customVC. At the very beginning I initialize my customVC like this from mainVC:
mainVC.m
customVC *cvc = [[customVC alloc] init];
[cvc setDelegate:self];
PopoverController *popover = [[PopoverController alloc] initWithViewController:cvc];
[popover presentPopoverFromView:textField];
I tried to instantiate a new instance of popoverVC inside my action method in customVC to be able to call the method [popoverdismiss]. But this should not be working since I will be targeting a different instance from the one I started with... And I would like to be able to target popoverVC like [self.presentingVC] but I am not sure the method initWithVC sets a hierarchy like this.
Does anyone has an idea?
The way I usually go about having to circumvent the default view controller hierarchy is to create a property within your child view controller (I think customVC) called parent or something to that effect that's of type mainVC. Then either create a new initializer for your customVC that incorporates a field to assign to parent or just assign to it after you first initialize your customVC. Then whenever your customVC needs to ask the mainVC to perform a function, you can make a method call from parent.
Alternatively, you could just as easily make parent correspond to your popoverVC object, I'm not totally sure which object you need to access, but it should be as simple as creating your own property for it.
Related
I have 2 view controllers . First one is UIview controller and second one is table view controller.
I want to send data 2nd (table view controller) to first(uiview Controller) after the selection of rows of 2nd view controller.
For this i have written a delegate protocol.
But my delegate protocol is not working...
I figured out the problem.The object of second view controller that i am creating.
address = [[second_viewcontroller alloc] init];
address.delegate = self;
is different from self of second_viewcontroller view controller page.
How to make this two same.
self = [[second_viewcontroller alloc] init];
your problem my delegate protocol is not working... I figured out the problem.The object of second view controller that I am creating. address=[[second_viewcontroller alloc]init]; address.delegate=self; is different from self of second_viewcontroller view controller page.
It's clear say that way you create the second_viewcontroller object is not right.
You have to create the object from ViewController storyboard identifier.
First give the Storyboard ID to ViewController from Storyboard.Follow this step to Giving the Storyboard ID.
Select the particular ViewController in Storyboard.
Go to IdentityInspector.
Under IdentityInspector, There is identity section and add the Storyboard ID In "Storyboard ID" Field.
Syntax For Creating a ViewController Object.
Second_viewController *aVC = [self.storyboard instantiateViewControllerWithIdentifier:#"Second_viewController"];
aVC.delegate = self;
I assume that you are calling the Second_ViewController from storyboard instead of doing programmatically.
In that case, the correct instance of Second_ViewController can be accessed in prepareForSegue. For that, you need to set a Storyboard segue identifier, eg "Second_ViewController"
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"Second_ViewController"]) {
SecondViewController *aSecVC = segue.destinationViewController;
// Register the Delegate to self.So when we call the delegate method from secondVC, SendMessage will be call of ViewController
aSecVC.delegate = self;
}
}
If you use alloc-init or instantiateViewControllerWithIdentifier, when you are using a storyboard push segue, it will create another instance.
Yes as your instantiating a new instance of the second view controller. From what I could make out from your question, I guess if you obtain the instance of your secondViewController from the Navigation Stack it should work
I created a sample project for you to get the basic knowledge of how to pass data backward using NSUserDefaults. try this in GitHub. hope this will help to you. project url Pass data backward using NSUserDefaults in Objective-C
I have declared a UIImageView (IBOutlet UIImageView *character;) in a file called GameViewController.h and I am unsure how I can access this from another file CharacterSelectViewController.h.
All I need to do with it after I get it is to set the image. How can I access this UIImageView from another file?
First you need to get the existing instance of GameViewController that is currently on display. How you do that from CharacterSelectViewController depends on how they are related to each other and you may want to set up a delegate relationship / navigate the view controller stack to find the correct instance.
Once you have the instance you just access the property:
gameViewController.character.image = ...;
In any case, a delegate type relationship is generally better than navigating the view controller hierarchy. This could be as simple direct relationship or a generalised relationship using an #protocol.
If GameViewController presented CharacterSelectViewController as a modal, then you could use
GameViewController *gameViewController = (GameViewController *)self.presentingViewController;
If GameViewController pushed CharacterSelectViewController into its navigation controller, then you could use:
NSArray *viewControllers = self.navigationController.viewControllers;
GameViewController *gameViewController = (GameViewController *) viewControllers[viewControllers.count - 2];
I've made a tabbar controller with two views (standard setup from the template). First view is accessing an array within an dataController object. When I tap to the second view on the tabbar, I want the dataController reference to be set on the second viewController's dataController property.
I use call
SecondViewController *vc = [[self storyboard] instantiateViewControllerWithIdentifier:#"SecondViewController"];
vc.dataController = self.dataController;
However, when I call my countArrayObjects on the secondViewController's dataController property, I always get 0 back - eventhough there should be objects in the array and I can't figure out why?
I've set the identifier on the secondViewController in MainStoryBoard and I have no crashes, the property just isn't set (I think).
For testing purposes I call the instantiateViewControllerWithIdentifier from a simple button, before tapping on to the secondView. And I call the countArrayObjects from viewDidLoad on secondViewController.
Any ideas?
Hmmm... I was having the same problem. At the moment, the only way I got around this is to test for the views superview being nil - which as its accessing the view selector of the class fires up the view did load event...
both of us are doing something wrong here though...
This is the test code I wrote...
SummaryViewController *sc = [self.childViewControllers objectAtIndex:0];
if(sc.view.superview == nil) sc.checkInTime.alpha = 0;
//-- by inspecting the value, it will call the viewDidLoad method of the controller.
It works, but it's wrong.
I got a view controller named IntroViewController in my storyboard and I want to add this as a child to another view controller like this:
IntroViewController *introViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"View1"];
[introViewController.textLabel setText:#"test"];
[self addChildViewController:introViewController];
On the IntroViewController I've put a label named textLabel on it in the storyboard, if I run the program it works and shows me the view controller, but the text doesn't get changed. Any idea how I can fix this?
When you instantiate a view controller from a storyboard, the view is not loaded until it is actually presented on screen. At the point in your code you have posted introViewController.textLabel is nil.
One option you could do is add a property to your IntroViewController class and instead set that:
introViewController.initialText = #"test";
Then, inside -viewDidLoad of your IntroViewController the label will be instantiated so you can make the call:
[self.textLabel setText:self.initialText];
It is also worth noting that most of the time it would be recommended to have a view controller be the one to set values on the views it owns, rather than some other view controller.
I would like to use my viewDidLoad function in my tableViewController.
How can I make viewDidLoad run in my controller?
tableViewController = [[TableViewController alloc] init];
UITableView *tableView = [[UITableView alloc] init];
tableViewController.view = tableView;
....
From Apple documentation:
This method is called after the view controller has loaded its view hierarchy into memory. This method is called regardless of whether the view hierarchy was loaded from a nib file or created programmatically in the loadView method. You usually override this method to perform additional initialization on views that were loaded from nib files.
So you can try to instantiate it from NIB or overwrite the loadView method. Another step from Apple documentation:
If you cannot define your views in a storyboard or a nib file, override the loadView method to manually instantiate a view hierarchy and assign it to the view property.
viewDidLoad will be called when the view is actually loaded, which will happen after you present your view controller, by, e.g.:
adding it to a navigation controller,
adding it to a tab bar controller,
presenting it modally.
This is the missing bit in your code. If you explain how you would like to present your view controller, I may help further. Also, have a look at this: Presenting View Controllers.
(I assume the fact that you tried to override the view property of your table view controller was just an attempt "to make things work" -- but you do not need to do anything about that, the view controller will be correctly set up with a table view inside of it).
tableViewController = [[TableViewController alloc] init];
tableViewController.tableView // This is your newly generated tableview
viewDidLoad will be called after you assign the tableView to another parentview