Search code examples
iosxcodestoryboardiboutlet

UIStoryboard Container Attach IBOutlet To Parent ViewController


I wanted to use a UITableView which contained static cells with a UITextField inside attached to my LoginViewController. I have added IBOutlets in the header file that correspond to the UITextFields in the storyboard. Unfortunately Xcode does not allow static content inside a UITableView you need to use a UITableViewController.

Therefore I split out the UITableView from the storyboard and used a ContainerView to embed a UITableViewController which works well. Attached a screenshot of the setup.

Current Storyboard Setup

The problem I am now facing is I cannot link the UITextFields to my LoginViewController, you can see from my screenshot that I have added an Object to the UITableViewController which I have set to my LoginViewController and managed to link the UITextFields to it. But when the main view loads it says my UITextFields are nil

How can I link my UITextFields to my IBOutlets in my LoginViewController?

Edit: If I have to subclass the UITableViewController it seems like I should have just used a prototype cell... Any other suggestions?


Solution

  • 1.) Name your embed segue to "TextFields"

    2.) If you haven't already, subclass UITableViewController and set your table view controller to this class in the storyboard. Let's call it TextFieldsTableViewController.

    3.) Again, if you haven't already, add IBOutlets for your text fields into TextFieldsTableViewController's public interface:

    @property (weak, nonatomic) IBOutlet UITextField *firstNameField;
    @property (weak, nonatomic) IBOutlet UITextField *usernameField;
    @property (weak, nonatomic) IBOutlet UITextField *emailField;
    @property (weak, nonatomic) IBOutlet UITextField *passwordField;
    

    4.) Add properties for your text fields into your LoginViewController's public interface (note that unlike the above, these are not weak (they are also not IBOutlets, but that doesn't really matter)):

    @property (nonatomic) UITextField *firstNameField;
    @property (nonatomic) UITextField *usernameField;
    @property (nonatomic) UITextField *emailField;
    @property (nonatomic) UITextField *passwordField;
    

    5.) In LoginViewController's prepareForSegue:sender: method, map the TextFieldsTableViewController's text fields to self's text fields after forcing the table view controller's view to load immediately:

    if ([segue.identifier isEqualToString:@"TextFields"]) {
    
        TextFieldsTableViewController *textFieldsVC = segue.destinationViewController;
    
        // IMPORTANT: This forces the view to load and the outlets to get set.
        // If you don't do this, textFieldsVC's IBOutlets will all be nil at this point.
        // This is slightly inelegant in my opinion, but it works. A better solution might
        // be to set the text fields in TextFieldsTableViewController's viewDidLoad method.
        [textFieldsVC view];
    
        self.firstNameField = textFieldsVC.firstNameField;
        self.usernameField = textFieldsVC.usernameField;
        self.emailField = textFieldsVC.emailField;
        self.passwordField = textFieldsVC.passwordField;
    }
    

    6.) You should now be able to access the text fields in LoginViewController's viewDidLoad method.