Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sending data with Segue with Swift

Tags:

ios

swift

segue

I have two view controllers and two views. In my first view, I set the variable 'currentUser' to false. I need to be able to set 'currentUser' to true in the second view controller.

When trying to reference 'currentUser' from the second view it's not picking it up as 'currentUser' is defined in the first view controller.

How do I carry across variables with segue?

like image 395
Alex Catchpole Avatar asked Sep 28 '14 20:09

Alex Catchpole


People also ask

How do I pass data to prepare for segue?

To pass data from the current view controller to the next new view controller (not a previous view controller) using segues, first create a segue with an identifier in the relevant storyboard. Override your current view controller's prepareForSegue method.

How do you pass data using segue and unwind in Swift?

You create the unwind segue as per usual - drag to the exit icon in the scene. Now in the object inspector on the left you will see the unwind segue listed below the view controller, first responder and exit icons. You can click on the unwind segue and give it an identifier in the inspector on the right.


2 Answers

Set values from Any ViewController to a Second One using segues

Like this:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {      if(segue.identifier == "yourIdentifierInStoryboard") {          let yourNextViewController = (segue.destinationViewController as yourNextViewControllerClass)         yourNextViewController.value = yourValue 

And in your yourNextViewController class.

class yourNextViewControllerClass {      var value:Int! // or whatever 

You can call this also programmatically:

 self.performSegueWithIdentifier("yourIdentifierInStoryboard", sender: self) 

Set values from your DestinationViewController back to your Primary (First) ViewController

1. Implement a protocol, for example create a file called protocol.swift.

    protocol changeUserValueDelegate {        func changeUser(toValue:Bool)     } 

2. set the delegate on your second View

    class yourNextViewControllerClass {      var delegate:changeUserValueDelegate? 

3. set the delegate on load (prepareForSegue)

    if(segue.identifier == "yourIdentifierInStoryboard") {          var yourNextViewController = (segue.destinationViewController as yourNextViewControllerClass)         yourNextViewController.delegate = self 

4. add Function to FirstViewController

    func changeUser(toValue:Bool) {         self.currentUserValue = toValue     } 

5. call this function from your SecondViewController

     delegate?.changeUser(true) 

6. Set the delegate in your FirstViewController

    class FirstViewController: UIViewController, ChangeUserValueDelegate { 
like image 160
derdida Avatar answered Sep 23 '22 03:09

derdida


The problem here is that your currentUser variable is of type Bool, which is a value type. So passing it from your first view controller to your second view controller will in fact create a new Bool instance. What you need is to pass a reference from your first view controller to your second view controller (see Value and Reference Types for more details on value and reference with Swift).

Thereby, according to your needs/preferences, you may choose one of the three following examples.


1. The boxing style

Here, we "box" our Bool inside a class and pass a reference of that class instance to the second view controller.

1.1. Create a CurrentUser class:

class CurrentUser {     var someBooleanValue = true {         didSet {             print(someBooleanValue)         }     } } 

1.2. Create a UIViewController subclass for the first view controller:

import UIKit  class ViewController1: UIViewController {      let currentUser = CurrentUser()          override func viewDidLoad() {         super.viewDidLoad()         currentUser.someBooleanValue = false     }          override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {         if let viewController2 = segue.destinationViewController as? ViewController2 {             viewController2.currentUser = currentUser         }     }  } 

1.3. Create a UIViewController subclass for the second view controller:

import UIKit  class ViewController2: UIViewController {      var currentUser: CurrentUser?      // Link this IBAction to a UIButton or a UIBarButtonItem in the Storyboard     @IBAction func toggleBoolean(sender: AnyObject) {         if let currentUser = currentUser {           currentUser.someBooleanValue = !currentUser.someBooleanValue         }     }      } 

2. The closure style

Here, we get a weak reference of our first view controller in a closure and pass this closure to the second view controller.

2.1. Create a UIViewController subclass for the first view controller:

import UIKit  class ViewController1: UIViewController {          var currentUser = true {         didSet {             print(currentUser)         }     }          override func viewDidLoad() {         super.viewDidLoad()         currentUser = false     }          override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {         if let viewController2 = segue.destinationViewController as? ViewController2 {             let closureToPerform = { [weak self] in                 if let strongSelf = self {                     strongSelf.currentUser = !strongSelf.currentUser                 }             }             viewController2.closureToPerform = closureToPerform         }     }      } 

2.2. Create a UIViewController subclass for the second view controller:

import UIKit  class ViewController2: UIViewController {      var closureToPerform: (() -> Void)?      // Link this IBAction to a UIButton or a UIBarButtonItem in the Storyboard     @IBAction func toggleBoolean(sender: AnyObject) {         closureToPerform?()     }      } 

3. The protocol-delegate style

Here, we make our first view controller conform to some protocol and pass a weak reference of it to the second view controller.

3.1. Create a custom protocol:

protocol MyDelegate: class {     func changeValue() } 

3.2. Create a UIViewController subclass for the first view controller and make it conform to the previous protocol:

import UIKit  class ViewController1: UIViewController, MyDelegate {      var currentUser = true {         didSet {             print(currentUser)         }     }          override func viewDidLoad() {         super.viewDidLoad()         currentUser = false     }          func changeValue() {         currentUser = !currentUser     }          override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {         if let viewController2 = segue.destinationViewController as? ViewController2 {             viewController2.delegate = self         }     }  } 

3.3. Create a UIViewController subclass for the second view controller:

import UIKit      class ViewController2: UIViewController {      weak var delegate: MyDelegate?      // Link this IBAction to a UIButton or a UIBarButtonItem in the Storyboard     @IBAction func toggleBoolean(sender: AnyObject) {         delegate?.changeValue()     }      } 
like image 34
Imanou Petit Avatar answered Sep 20 '22 03:09

Imanou Petit