1

In my application I have this view controller where the user inputs information to create an object pretty much. At the top of this view I have a tab bar and at the bottom I have a button that the user taps to create/save the object. In between those two views I have some elements such as text fields, labels, and a few other things that the user inputs the information of the object into, (basically a form for the object).

I'm now trying to support landscape mode as well as add a few more forms to this view controller. Problem is on smaller devices and in landscape all of the form elements and text fields, etc won't fit.

I'm trying to use a scroll view to solve this. I used this Stack Overflow answer to get the scroll view working in a test project (before I port the concepts to my actual project).

Only trouble is if I can't pin a button to the bottom of the screen using that method. To solve that I've created a container view inside of the main view controller (view controller A). That container view maps to the view controller (view controller B) that houses the scroll view and contents. Then right below the container view in view controller A I was able to add the create/save button. That seems to work perfectly from a design perspective. But now that the content is in a separate view controller from the create/save button I can't actually get the contents and inputs from what the user enters into the text fields.

What is the best way to handle a situation like this? Is using a container view really the best method here? Is there a simple way to map those inputs from the text fields back to the main view controller?

If possible I'd like to keep as much of the design work in the Storyboard as possible. Adding views and design elements in Swift would be a last resort. But I'm pretty sure I'll need to use some type of code to get that data back to the main view controller which is totally ok.

Community
  • 1
  • 1
Charlie Fish
  • 18,491
  • 19
  • 86
  • 179
  • As I understand, B is a child view controller of A? If that is correct, could you please tell me if you are adding it as a child in your code? – Andriy Gordiychuk May 06 '17 at 21:14
  • @AndriyGordiychuk I had my normal default view controller (view controller A). I then dragged a container view onto that default view controller. It created a view inside of view controller A and created a new view controller (view controller B). This was all done in the storyboard with no code at all. Inside of the view controller B I have the scroll view and contents and all of that. Inside view controller A I have just the container view (which is linked to view controller B, through some embed segue or something like that) and a create/save button at the bottom. – Charlie Fish May 06 '17 at 21:17
  • @AndriyGordiychuk Let me know if that doesn't make sense. – Charlie Fish May 06 '17 at 21:17
  • 1
    makes sense will tell you know how to resolve your issue – Andriy Gordiychuk May 06 '17 at 21:20

1 Answers1

1

The easiest way for you to achieve the behaviour that you want is the following:

1) Specify custom identifier for the embed segue which is created for you in IB. For example, "embedViewControllerB"

2) In view controller A add the following parameter:

weak var viewControllerB: ViewControllerB?

3) In view controller A override prepare(for segue:) function. Check if the segue is your embed one and if so, store reference to the B controller:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "embedViewControllerB" {
        self.viewControllerB = segue.destination as! ViewControllerB
    }
}

Now when you click on your button you can get access to the contents of view controller B through the viewControllerB? property.

At this stage it is up to you to decide how to proceed. You can either setup IBOutlets to the text views in B and read contents of them in A, or you can implement some function in B which would return the necessary data (maybe in a tuple?).

Hope this helps

Andriy Gordiychuk
  • 6,163
  • 1
  • 24
  • 59
  • So sorry it's taken me so long to reply. Taken longer to implement then I thought. So instead of `segue.destinationController` I had to rename it to `segue.destination` just so future viewers know (in Swift 3). I'm also getting an error when trying to access the variable in view controller A: `Value of type 'UIViewController?' has no member 'textField'`. Any ideas? – Charlie Fish May 06 '17 at 22:34
  • You need to have '@IBAction var textField:UITextField!' to access it. Otherwise, obviously, you can't have access to it :) – Andriy Gordiychuk May 06 '17 at 22:35
  • I have `@IBOutlet var textField: UITextField!` in View Controller B. – Charlie Fish May 06 '17 at 22:37
  • In View Controller A the line that's giving that error is `self.viewControllerB.textField.text!` – Charlie Fish May 06 '17 at 22:37
  • make sure that the variable which points to view controller B is declared as having class of view controller B. Otherwise, if it is declared as UIViewController you can't access the outlet – Andriy Gordiychuk May 06 '17 at 22:38
  • there seems to be extra space in the line which you posted – Andriy Gordiychuk May 06 '17 at 22:38
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/143587/discussion-between-andriy-gordiychuk-and-charlie-fish). – Andriy Gordiychuk May 06 '17 at 22:38