0

I have two VCs in my project. I have a UIButton that segues to the second VC. I have data being sent to this VC. I want the second VC to be able to add to the array that is sent and then send it back. In my main VC I have:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

    let toViewController = segue.destination as! SaveViewController
    toViewController.masterView = self

In the second VC I have:

var masterView:UIViewController!

...

override func viewWillDisappear(_ animated: Bool) {
     masterView.listArray = listArray
 }

What I am getting is

Value of type 'UIViewController' has no member 'listArray.'

The listArray is declared in both VCs. If this is a correct way to go about doing what I am trying to do, I am obviously assuming that I must do some more configuring in the second ViewController in order to make the other VC accessible.

Gaurav Patel
  • 532
  • 1
  • 5
  • 19
r405
  • 31
  • 4
  • `masterView` is a normal `UIViewController `, that doesn't contain a `listArray`. You should declare it with the type of your first UIViewController. – Marco Pace May 23 '18 at 07:58

2 Answers2

2

Probably this is not the right way to pass data back the the previous view controller. Although there are other options that you can follow to achieve the desired functionality, I would recommend to follow the Delegation pattern approach.

For your case, you could do it like this -for instance-:

According to "How to Apply Delegation?" section in this answer, the first thing that we should do is to implement the needed protocol:

protocol SaveViewControllerDelegate: class {
    // I assumed that 'listArray' is an array of strings, change it to the desired type...
    func saveViewControllerWillDisappear(_ listArray: [String], viewController: UIViewController)
}

Thus in SaveViewController, you should create -weak- instance of SaveViewControllerDelegate and call its method at for the desired behavior:

class SaveViewController: UIViewController {
    weak var delegate: SaveViewControllerDelegate? = nil
    var listArray: [String]!

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)

        // assuming that you already did the required update to 'listArray'
        // you would need to pass it here:
        delegate?.saveViewControllerWillDisappear(listArray, viewController: self)
    }
}

So far we added the necessary code for the SaveViewController, let's jump the the MasterViewController (first view controller):

Next, you would need to conform to SaveViewControllerDelegate, Connecting the delegate object and implement its method (steps from 2 to 4 in the mentioned answer):

class MasterViewController: UIViewController, SaveViewControllerDelegate {
    var listArray: [String]!

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        let toViewController = segue.destination as! SaveViewController

        // make sure to add this:
        toViewController.delegate = self

        toViewController.listArray = self.listArray
    }

    func saveViewControllerWillDisappear(_ listArray: [String], viewController: UIViewController) {
        print("here is my updated array list: \(listArray)")
    }
}

At this point, saveViewControllerWillDisappear method should be get called when coming back from SaveViewController, including listArray as a parameter.


Aside note:

The reason of the error that you are facing is that you are declaring masterView as UIViewController, what you should do instead is:

var masterView:MasterViewController!

HOWEVER keep in mind that this approach still -as I mentioned before- inappropriate one.

Ahmad F
  • 30,560
  • 17
  • 97
  • 143
  • ListArray was intended to be a multidimensional array of string arrays. I’ve looked deeper into this and I still am struggling to grasp delegates, but I am getting closer. Your answer did help quite a bit. I think I need a day or two to absorb the whole concept. Thanks. – r405 May 23 '18 at 22:06
  • 1
    @r405 don't hesitate to ask about any faced issue :) – Ahmad F May 23 '18 at 23:28
  • I have a couple questions. after the SaveViewController class you put "UITableViewDelegate" as a parameter. Must this always be called when declaring a protocol/delegate? Also, am I correct in noticing that the protocol is declared in the main VC, as I see that its function is defined there? Just want to be thorough. Thank you very much. – r405 May 24 '18 at 00:30
  • Oh actually it is a mistake, sorry about that :) Answer edited. – Ahmad F May 24 '18 at 07:38
  • Alright just one more question. To store the updated array in the main VC, do I store it in a variable within the protocol? or is the function you provided making it accessible in the main VC already? Thanks – r405 May 25 '18 at 00:14
0

This happens because UIViewController has no element listView.

Change MasterView type to:

var masterView: FirstViewController!
FelixSFD
  • 6,052
  • 10
  • 43
  • 117