Accessing another View Controller's IBOutlets Housed in a Container View - ios

I have a Container View that holds 1 of 3 view controllers swapped out by 3 tabs (across the bottom).
Here's my Storyboard:
I'm taking this approach so that I can have custom tabs and a single Save button for all the fields in this big form.
How can I access the IBOutlets in those 3 child view controllers from inside my Entry Detail View Controller class?
Here's what I've done to try and access it in the parent.
//EntryFlightInfoViewController.h (Child 1)
#property (strong, nonatomic) IBOutlet UITextField *aircraftIdTextField;
Then in my parent class (Entry Detail View Controller) I can't access the property:
//EntryDetailViewController.m (Parent)
#import "PPEntryFlightInfoViewController.h"
- (IBAction)buttonSave:(id)sender {
NSLog(#"save: %#", _aircraftIdTextField); //(!) Error: Use of undeclared identifier '_aircraftIdTextField'
}
How do I access another view controller's IBOutlets when they are in a Container View? Hopefully I'm on the right track. Forgive me as I'm still quite new to Objective-C. :)

View controllers in a container view are children of the controller with the container view. So, you can access the current child view controller with self.childViewControllers[0], and the outlet with [self.childViewControllers[0] aircraftIdTextField]

The short answer is you can't unless you write your own communication layer. You can get at the different views via the childViewControllers (mentioned above) as well as getting your own custom pointers in your prepareForSegue method call as the view is loaded into the container view. (see this link for more info on this) This will work great if you are forcing the user to visit each page. If not then the same defaults you'd load there on the first viewDidLoad can likely be saved without checking the specific view controller.
Apple's answer is to never have a save button. If you edit it, you meant it, and it's saved immediately. =)
That said, were I you, I'd have an object that all of the views access to load/unload their data for storage whenever you show/hide the different views, possibly in viewDidLoad/viewDidDisappear. This way you always have a "known good" object ready for saving, and you won't have to directly access those view controllers.
Hope that helps some.

Clifton, whenever you can, you should avoid having VCs know about each others' controls. You could just have the save button send out a message, and have the three subordinate VCs observe for it. When they get the message, they save their info. That way, the master VC doesn't have to know about controls inside its subordinates.

You need a reference to the current tab view controller, then you ask it for the outlet:
self.entryFlightInfoViewController.aircraftIdTextField
By trying to use _aircraftIdTextField your trying to directly access an instance variable on the container view controller class. Obviously if doesn't have a variable with that name so you get the compile error.

Related

Update UI from another controller

I would like to update my UILabel on click the button of ContainerView contains table ViewController. When I try to do this UILabel's outlets reference shows nil value exception. I am using Swift3 with Xcode8
Most probably the problem you are seeing is due to the fact that the view that owns this label on another view controller is still not loaded.
This happens often, basically because views owned by a view controller are instantiated in a lazy manner, this means that they are loaded only when required.
To fix that before setting the value on the label, just preload the view by doing something like.
_ = another_viewcontroller_instance.view
In this way you are forcing the destination view controller to load the view and creating all the necessary connection on the xib.
Even if this fix works, this is not a good way to deal with this kind of pattern (sending info from a VC to another), but since you didn't gave us any further detail this is the only solution I have.

View as SubView VS ChildViewController

Can any one explain when should we add a UIViewController as ChildViewController?
What is the benefits of adding it as ChildViewController instead of subView?
Please help me to understand the purpose of ChildViewController.
When you add a view controller as child view controller, the parent view controller will hold a strong pointer to the child view controller so it doesn't get released instantly. This does not automatically add child's view to parent's view. So you will have to call them both.
I only used it when I needed to create multiple view controllers to be inserted in another view controller and didn't need to directly access it.
its all about UI and code management if you are using subview to achieve what you want to implement inside your app you need to code for your view inside same viewcontrollers class but something interesting i found by creating childviewcontrollers.
empowered to work on a seprate viewcontroller will invoked along with its parent viewcontroller along with its seprate class.
infinite controllers that will be updated tapping a button.
Creation of childViewControllers can be achived by implementing containerView.
or you must have a look of this link hope its helpful to understand.

How can I link an outlet from a view controller to an other?

I am working on an app that uses parse so I used the "starter project" as a base and worked from there.
The issue I am facing is that the ViewController is controlling the login screen a well as others such as the tableView and mapView witch I added later.
As this is the case if it would be possible I would link the map outlet by simply dragging from the code to the map but obviously this is not possible, How could I solve this problem (I understand I may be looking at the problem the wrong way but any help would be appreciated)
here is the code with the map outlet
here is what the layout looks like
The MVC model, Model-View-Controller model, isn't intended to have an action in one view touch the controller of another view. In InterfaceBuilder, you should only ever be able to attach actions to the controller for that specific view.
In general, if you set the file owner to ViewController, then you can only link IBoutlets to that view controller not make to another one.
your map is available in your MapViewController not ViewController, so you need to give the reference/IBoutlet of map need to assign the MapViewController, if you want to implement in ViewController, you need to create new one map
No you have to create different file for each controller.
you cant add outlet of all in one controller

Accessing a ViewController's subview that's added on the storyboard

Please see the image below for a storyboard visual. I have a ViewController called StudioViewController (It's labeled ViewController on the storyboard). And I have a UIScrollView that's called CanvasViewController (the thing to the right of the view controller that actually sits on top of the View Controller). I want to be able to access the CanvasViewController in the StudioViewController class, how do I do that? Because I created it in the storyboard here, I dont' seem to have a variable that allows me to access the CanvasViewController... Should I create it in code instead, or is there some obvious way to access it that I'm completely missing?
Thanks
******** UPDATE *********
The question has been answered in the comments below by rdelmar:
You could make a shared variable in the app delegate. This is not very secure but I have resulted to this when I can't access a child or parent due to page transitions.

TableView index from rootcontroller to detailcontroller (UINavigationController)

My root view is a grouped tableview. When the user selects a row, i want to be able to retain which row was selected to give to the detailcontroller for loading the correct data.
All the navigation is working fine, I just don't want to have to create a global variable to just retain the index. Is there a built in method for the navcontroller or something?
You can either set a property in you detail view controller before it is pushed giving info about the row selected so it can influence the behaviour of the detail view controller, or it is possible to access the parent view controller directly from the detail view controller with:
#property(nonatomic, readonly) UIViewController *parentViewController
I prefer the first option - you can write a custom init... method, to supply the data for the detail view controller when it's created.
There isn't a builtin way as such, you should try and make the view controllers de-coupled as possible so they can be re-used and are resistent to changes elsewhere in the app.
This is a useful quote from the View Controller Programming Guide for iOS:
With the exception of view controllers managing leaf data, each custom view controller must provide a way for the user to navigate to the next level of the data hierarchy. A view controller that displays a list of items can use taps in a given table cell to display the next level of data. For example, when a user selects a photo album from the top-level list, the Photos application creates a new photo album view controller. The new view controller is initialized with enough information about the album for it to present the relevant photos.
I wanted to follow up with how I ended up coding this. I'm still somewhat new to Obj-C, so some concepts I haven't dealt with or come across, so if this is old hat, sorry.
You can create your data element in the child controller and pass the data 1 for 1 directly to that element by accessing its property.
ParentController.h
NSDictionary *myData;
ChildController.h
NSDictionary *childData;
// This would get called in the parent controller where appropriate
// but before the child controller is presented
ChildController.childData = myData;
This is obviously very stripped down, but the idea works. Just take your data and pass it to the property before calling it and it will be there once the child view is presented. Hope this helps.

Resources