web-dev-qa-db-fra.com

Envoi de données avec Segue avec Swift

J'ai deux contrôleurs de vue et deux vues . Dans ma première vue, j'ai défini la variable "currentUser" sur false .

Lorsque vous essayez de référencer 'currentUser' à partir de la deuxième vue, il ne la détecte pas car 'currentUser' est défini dans le premier contrôleur de vue.

Comment puis-je transporter des variables avec segue?

34
Alex Catchpole

Définissez les valeurs de Any ViewController sur un second à l'aide de segues  

Comme ça:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {

    if(segue.identifier == "yourIdentifierInStoryboard") {

        let yourNextViewController = (segue.destinationViewController as yourNextViewControllerClass)
        yourNextViewController.value = yourValue

Et dans votre classe yourNextViewController.

class yourNextViewControllerClass {

    var value:Int! // or whatever

Vous pouvez appeler cela aussi par programme:

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

Définissez les valeurs de votre DestinationViewController dans votre ViewController (premier) principal  

1. Implémentez un protocole, par exemple créez un fichier appelé protocole.Swift.

    protocol changeUserValueDelegate {
       func changeUser(toValue:Bool)
    }

2. définir le délégué sur votre deuxième vue

    class yourNextViewControllerClass {

    var delegate:changeUserValueDelegate?

3. définir le délégué en charge (prepareForSegue)

    if(segue.identifier == "yourIdentifierInStoryboard") {

        var yourNextViewController = (segue.destinationViewController as yourNextViewControllerClass)
        yourNextViewController.delegate = self

4. ajouter une fonction à FirstViewController

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

5. appelez cette fonction à partir de votre SecondViewController

     delegate?.changeUser(true)

6. Définir le délégué dans votre FirstViewController

    class FirstViewController: UIViewController, ChangeUserValueDelegate {
56
derdida

Le problème ici est que votre variable currentUser est de type Bool, qui est un type valeur. Donc, le passer de votre premier contrôleur de vue à votre second contrôleur de vue créera en fait une nouvelle instance Bool. Ce qu'il vous faut, c'est transmettre une référence de votre premier contrôleur de vue à votre second contrôleur de vue (voir Types de valeur et de référence pour plus de détails sur la valeur et la référence avec Swift).

Ainsi, selon vos besoins/préférences, vous pouvez choisir l’un des trois exemples suivants.


1. Le style de boxe

Ici, nous "boxons" notre Bool à l'intérieur d'une classe et passons une référence de cette instance de classe au second contrôleur de vue.

1.1. Créez une classe CurrentUser:

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

1.2. Créez une sous-classe UIViewController pour le premier contrôleur de vue:

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. Créez une sous-classe UIViewController pour le second contrôleur de vue:

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. Le style de fermeture

Ici, nous obtenons une référence faible de notre premier contrôleur de vue dans une fermeture et passons cette fermeture au second contrôleur de vue.

2.1. Créez une sous-classe UIViewController pour le premier contrôleur de vue:

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. Créez une sous-classe UIViewController pour le second contrôleur de vue:

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. Le style de délégué de protocole

Ici, nous faisons en sorte que notre premier contrôleur de vue se conforme à un protocole et en transmettons une faible référence au second contrôleur de vue.

3.1. Créez un protocole personnalisé:

protocol MyDelegate: class {
    func changeValue()
}

3.2. Créez une sous-classe UIViewController pour le premier contrôleur de vue et conformez-le au protocole précédent:

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. Créez une sous-classe UIViewController pour le second contrôleur de vue:

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()
    }

}
14
Imanou Petit

Ajoutez un attribut currentUserSecondVC dans le contrôleur de vue de destination et utilisez prepareForSegue

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if segue.identifier == "Name Of Your Segue" {
        var vc = segue.destinationViewController as NameOfTheSecondViewController
        vc.currentUserSecondVC = !currentUser //you can do whatever you want with it in the 2nd VC
    }
}
1
Carpsen90

La fonction qui devrait être définie comme remplacement est la suivante:

open func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if (segue.identifier == "Segue Name Defined In Storyboard") {
        //set the property of the designated view controller with the value you need
    }
}
0
Trombe

Puisque vous utilisez la même variable sur les deux Viewcontrollers, à savoir currentUser (type Bool).

Il vaut donc mieux en faire une variable globale dans les deux classes.

En venant au concept de variable globale dans Swift.  

Tout par défaut dans Swift est public, et donc si vous déclarez quelque chose comme ceci:

class FirstViewController: UIViewController {

    var someVariable: Boll = YES

    init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
    }
}

Vous pouvez y accéder et définir des valeurs tant que vous en avez une instance:

var MySecondViewController: FirstViewController = FirstViewController(nibName: nil, bundle: nil)
var getThatValue = MySecondViewController.someVariable
0
Saranjith