web-dev-qa-db-fra.com

Accédez à l'instance d'un Viewcontroller à partir d'un autre dans swift

J'essaie de transférer des données du champ de texte d'un View Controller vers l'étiquette d'un autre.

Comment puis-je appeler l'instance de View Controller à partir du code de l'autre View Controller? Je travaille avec des storyboards donc je n'ai jamais créé d'instance des View Controllers dans le code? Les instances sont-elles créées automatiquement? Et quel nom ont-ils?

Merci de votre aide!

28
McLawrence

1. Si le contrôleur de vue contenant le champ de texte peut appeler (avec une séquence) le contrôleur de vue contenant l'étiquette ...

Ajoutez un nouveau fichier de classe Cocoa Touch dans votre projet, nommez-le FirstViewController et définissez-y le code suivant:

import UIKit

class FirstViewController: UIViewController {

    @IBOutlet weak var textField: UITextField! // FIXME: link this to the UITextField in the Storyboard!!!

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        let controller = segue.destinationViewController as! SecondViewController
        controller.text = textField.text
    }

}

Ajoutez un nouveau fichier de classe Cocoa Touch dans votre projet, nommez-le SecondViewController et définissez-y le code suivant:

import UIKit

class SecondViewController: UIViewController {

    var text: String?
    @IBOutlet weak var label: UILabel! // FIXME: link this to the UILabel in the Storyboard!!!

    override func viewDidLoad() {
        super.viewDidLoad()

        label.text = text
    }

}

Dans le Storyboard, intégrez le premier contrôleur de vue dans un UINavigationController. Reliez le premier contrôleur de vue au second avec un UIButton ou un UIBarButtonItem. Définissez le nom du premier contrôleur de vue sur FirstViewController et le nom du deuxième contrôleur de vue sur SecondViewController. Créez un UITextField dans le premier contrôleur de vue. Créez un UILabel dans le deuxième contrôleur de vue. Liez le champ de texte et l'étiquette à leurs déclarations respectives dans FirstViewController et SecondViewController.


2. Si le contrôleur de vue contenant l'étiquette peut appeler (avec une séquence) le contrôleur de vue contenant le champ de texte ...

Ici, c'est un cas parfait de protocole/délégué. Vous pouvez trouver beaucoup de choses sur StackOverflow traitant de cela. Cependant, voici un exemple approximatif.

Ajoutez un nouveau fichier de classe Cocoa Touch dans votre projet, nommez-le FirstViewController et définissez-y le code suivant:

import UIKit

class FirstViewController: UIViewController, DetailsDelegate {

    @IBOutlet weak var label: UILabel! // FIXME: link this to the UILabel in the Storyboard

    func updateLabel(withString string: String?) {
        label.text = string
    }

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        let controller = segue.destinationViewController as! SecondViewController
        controller.delegate = self
    }

}

Ajoutez un nouveau fichier de classe Cocoa/Cocoa Touch dans votre projet, nommez-le SecondViewController et définissez-y le code suivant:

import UIKit

protocol DetailsDelegate: class {
    func updateLabel(withString string: String?)
}

class SecondViewController: UIViewController {

    weak var delegate: DetailsDelegate?
    @IBOutlet weak var textField: UITextField! // FIXME: link this to the UITextField in the Storyboard

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

        delegate?.updateLabel(withString: textField.text)
    }

}

Dans le Storyboard, intégrez le premier contrôleur de vue dans un UINavigationController. Reliez le premier contrôleur de vue au second avec un UIButton ou un UIBarButtonItem. Définissez le nom du premier contrôleur de vue sur FirstViewController et le nom du deuxième contrôleur de vue sur SecondViewController. Créez un UILabel dans le premier contrôleur de vue. Créez un UITextField dans le deuxième contrôleur de vue. Liez le champ de texte et l'étiquette à leurs déclarations respectives dans FirstViewController et SecondViewController.

20
Imanou Petit

Imanou Petit et Oscar Swanros ont déjà répondu correctement. Cependant, il existe une alternative qui est plutôt "hacky" que j'ai dû utiliser pour transférer des données entre 2 contrôleurs de vue sans enchaînement les reliant.

Pour obtenir le contrôleur de vue racine de votre application, vous pouvez:

UIApplication.sharedApplication().windows[0].rootViewController

De là, vous pouvez obtenir le contrôleur de vue de votre choix. Par exemple, si vous voulez le deuxième contrôleur de vue enfant du contrôleur de vue racine, vous feriez:

let viewController = UIApplication.sharedApplication().windows[0].rootViewController?.childViewControllers[1] as? YourViewController
viewController?.yourProperty = newValue

Gardez à l'esprit que cette approche est plutôt "hacky" et viole probablement les meilleures pratiques de codage.

14
João Neves

Vous devez créer une transition entre les contrôleurs de vue:

  1. Sur votre Storyboard, sélectionnez ViewController A.
  2. Tout en maintenant le Control, cliquez sur ViewController A, faites glisser et déposez la ligne bleue sur ViewController B. Si ViewController A est intégré dans un NavigationController, sélectionnez "afficher" dans le menu qui apparaît lorsque vous lâchez prise. Sinon, sélectionnez "présenter de façon modale".
  3. Sélectionnez la séquence sur votre Storyboard, et dans le panneau Utilitaires, accédez à l'inspecteur d'attributs et attribuez un identifiant à votre séquence (par exemple: "DetailSegue").

Maintenant, lorsque vous voulez déclencher la séquence sur ViewController A, il vous suffit d'appeler (peut-être en appuyant sur un bouton):

@IBAction func buttonTapped() {
    self.performSegueWithIdentifier("DetailSegue", sender: self)
}

Pour passer une valeur à ViewController B, remplacez le prepareForSegue:sender méthode sur ViewController A:

override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
    if segue.identifier == "DetailSegue" {
        var viewControllerB = segue.destinationViewController as ViewControllerB
        viewControllerB.text = self.textField.text
    }
}

Assez simple.

Notez que pour que cela fonctionne, votre ViewController B la classe devrait ressembler à ceci:

class ViewControllerB: UIViewController {
    ver label = UILabel(...)
    var text: String? 

    override func viewDidLoad() {
        super.viewDidLoad()

        label.text = text!
    }
}

J'espère que cela t'aides.

5
Oscar Swanros