1

I've been struggling for a few days now with passing an array from my SecondViewController to my FirstViewController using Swift.

From my research I found that segue with prepareForSegue would be a viable option but I can't seem to figure it out. What am I doing wrong?

My prepareForSegue in SecondViewController looks like this:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        var DVC: FirstViewController = segue.destinationViewController as! FirstViewController
        DVC.mySeguedArray = myIncomeArray
}

My FirstViewController looks like this:

class FirstViewController: UIViewController {
@IBOutlet weak var textView: UITextView!
var myIncomeArray: [Income] = []
var mySeguedArray: [Income] = []

override func viewDidLoad() {
    super.viewDidLoad()
    myIncomeArray = mySeguedArray
}

Also worth mentioning is that I'm sure I'm populating the array in the SecondViewController as I'm testing it by printing out the size of the array when adding new Income objects to it. But the array in FirstViewController just returns 0 when checking it size after segue.

Edit: Added picture of storyboard StoryBoard

10
  • what does initiate the segue back to first vc? and do you have navigation controller in between or is it a show detail segue or something else? Commented Oct 12, 2015 at 21:29
  • I tried now to ctrl + drag on the storyboard from the add button on my add button on the SecondViewController to my FirstViewController but it's only letting me push, modal & custom. Commented Oct 12, 2015 at 21:59
  • push is fine, but make sure you put the correct segue id in the attribute inspector Commented Oct 12, 2015 at 22:01
  • Getting the following error after creating a push between the button and the FirstViewController. *** Terminating app due to uncaught exception 'NSGenericException', reason: 'Could not find a navigation controller for segue 'passArray'. Push segues can only be used when the source controller is managed by an instance of UINavigationController.' Commented Oct 12, 2015 at 22:15
  • embed the first vc in navigation controller Commented Oct 12, 2015 at 22:24

3 Answers 3

1

Did you know that array in Swift are value type. So, when you assign array to some other variable or pass it to some method, the value is passed; not the reference to actual object. When you pass your array to second view controller, it copies the content of your original array. You are then adding to this array which do not change the content of original array.

I would suggest you to create some kind of callback or delegate pattern from second view controller to first view controller to inform the changes such that first view controller would also modify the original array content.

Here is a small portion of code that will help you understand this,

let originalArray = ["a", "b", "c"]

var newArray = originalArray

newArray.append("d")

print(originalArray) // prints ["a", "b", "c"]
print(newArray) // prints ["a", "b", "c", "d"]
Sign up to request clarification or add additional context in comments.

1 Comment

Alright, I will look into that tomorrow. But as long as I can override the array each time I segue, then it won't be an issue since my FirstViewController is only where I want to display them in a textView.
1

You can use protocol to pass data between view controllers

protocol YourFirstViewControllerDelegate: class {
    func onButtonClicked(yourString: [String])
}

For passing data from first view controller to second in your Main view Controller when you want to show your first view controller:

  1. you should set main view controller to your view controller delegate, yourFirstViewController.setDlegate(self)

  2. In FirstViewController you should raise an event to main with onButtonClicked([String])

  3. In onButtonClicked([String]) you can call secondViewController and pass your array with onSecondViewController([String])

    class MainViewController: UIViewController,YourFirstViewControllerDelegate{
    var yourString = [String]()
    weak var vcFirst: FirstViewController?
    weak var vcSecond: SecondViewController?
    func onFirstViewController(){
    
        if (self.vcFirst == nil){
            self.vcFirst = self.storyboard?.instantiateViewController(withIdentifier: "FirstViewController") as? FirstViewController
            self.vcFirst!.view.translatesAutoresizingMaskIntoConstraints = false
            self.vcFirst?.setDelegate(youeFirstViewControllerDelegate: self)
        }
        self.setActiveController(viewController: self.vcFirst)
    
    }
    
    func onSecondViewController(yourString:[String]){
        if (self.Second == nil){
            self.Second = self.storyboard?.instantiateViewController(withIdentifier: "SecondViewController") as? SecondViewController
            self.vcSecond!.view.translatesAutoresizingMaskIntoConstraints = false
    self.vcSecond.setArray(yourArray: self.yourArray)
        }
        self.setActiveController(viewController: self.vcSecond)
    
    }
    
    ....// your view controller method
    
    func onButtonClicked(yourString: [String]){
    self.yourString = yourString
    onSecondViewController(yourString:self.yourString)
    }
    

In your First view controller

class FirstViewController: UIViewController{
    weak var yourFirstViewControllerDelegate: YourFirstViewControllerDelegate?
    var yourString = ["test1","test2"]
//  all your overide method should be here
    func setDelegate(yourFirstViewControllerDelegate:  YourFirstViewControllerDelegate){ 
    self.yourFirstViewControllerDelegate = yourFirstViewControllerDelegate
  }

func onButtonClicked(){
     self.yourFirstViewControllerDelegate.onButtonClicked(self.yourString)
    }

In your second view controller

class SecondViewController: UIViewController{
var yourString = [String]
//  all your overide method should be here and you can use your [String]
 func setArray(yourString:[String]){
 self.yourString = yourString
 }
}

I have not Mac OS to check my code now please just read this code not copy, I'll edit this code tomorrow

Comments

0

Your code looks fine, use the following prepareforsegue as it helps figure out where the problem could be

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if segue.identifier == "segueIdInStoryboard" {
        if let DVC = segue.destinationViewController as? FirstViewController{
            DVC.mySeguedArray = myIncomeArray
        } else {
            print("Data NOT Passed! destination vc is not set to firstVC")
        }
    } else { print("Id doesnt match with Storyboard segue Id") }
}

class FirstViewController: UIViewController 
{
     @IBOutlet weak var textView: UITextView!
     var myIncomeArray: [Income]!
     var mySeguedArray: [Income]!{
         didSet{
             myIncomeArray = mySeguedArray //no need to call viewDidLoad
         }
     }
}

2 Comments

Everything with the segue works fine, but it seems like it creates a new empty myIncomeArray every time I navigate to the SecondViewControllerwith one exception, if I press the Back button from the FirstViewController. Then it keeps the data.
Alright, I have managed to solve the problem. I did it by implementing a prepareForSegue in the FirstViewControlleras well. So I always pass around the same array and not initialise a new one. Thank you all for your answers, I've learned a lot!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.