J'ai créé deux contrôleurs de vue. J'ai créé une séquence du premier au second pour transmettre les données. Maintenant, je veux transmettre des données du deuxième contrôleur de vue au premier. J'ai parcouru de nombreuses questions similaires et je ne suis pas en mesure de les mettre en œuvre car je ne sais pas comment fonctionne le déroulement.
ViewController.Swift
class ViewController: UIViewController
{
var dataRecieved: String?
@IBOutlet weak var labelOne: UILabel!
@IBAction func buttonOne(sender: UIButton)
{
performSegueWithIdentifier("viewNext", sender: self)
}
override func prepareForSegue(segue: (UIStoryboardSegue!), sender: AnyObject!)
{
var svc: viewControllerB = segue.destinationViewController as! viewControllerB
svc.dataPassed = labelOne.text
}
}
Cela transmettra les données à dataPassed dans le contrôleur de vue "viewControllerB". Dis, maintenant je veux passer des données de viewControllerB à dataRecieved dans ViewController. Comment est-ce que je peux faire ceci avec seulement dérouler segue et pas en utilisant délégué. Je suis assez nouveau pour Swift, j'aimerais une explication détaillée.
Øyvind Hauge m'a battu à la même méthode de solution , mais comme j'avais déjà commencé avec une réponse plus détaillée, je vais l'ajouter également.
Supposons que vos deux contrôleurs de vue soient nommés comme suit:
ViewController
(vcA)
ViewControllerB
(vcB)
Vous avez configuré la séquence à partir de (vcA) -> (vcB)
comme vous l'avez fait dans votre exemple
/* in ViewController.Swift */
// ...
// segue ViewController -> ViewControllerB
override func prepareForSegue(segue: (UIStoryboardSegue!), sender: AnyObject!)
{
if segue.identifier == "viewNext" {
let viewControllerB = segue.destinationViewController as! ViewControllerB
viewControllerB.dataPassed = labelOne.text
}
}
L'étape quelque peu délicate suivante est que, en utilisant cette méthode, la séquence utilisée pour renvoyer les données à partir de (vcB)
à (vcA)
est également ajouté à la source de (vcA)
, en tant que @IBAction
méthode (plutôt que, comme on pouvait s'y attendre, ajoutée à la source de (vcB)
).
/* in ViewController.Swift */
// ...
// segue ViewControllerB -> ViewController
@IBAction func unwindToThisView(sender: UIStoryboardSegue) {
if let sourceViewController = sender.sourceViewController as? ViewControllerB {
dataRecieved = sourceViewController.dataPassed
}
}
Vous vous connectez ensuite, disons, un bouton dans (vcB)
à cette action de déroulement dans (vcA)
via le manuel Exit
segue in (vcB)
:
Ci-dessous, un exemple complet de passage de texte de (vcA)
à (vcB)
; (éventuellement) modifier ce texte via un UITextField
, renvoyant finalement le texte (éventuellement) modifié à (vcA)
.
(vcA)
la source:
/* ViewController.Swift: Initial view controller */
import UIKit
class ViewController: UIViewController {
var dataRecieved: String? {
willSet {
labelOne.text = newValue
}
}
@IBOutlet weak var labelOne: UILabel!
@IBAction func buttonOne(sender: UIButton) {
performSegueWithIdentifier("viewNext", sender: self)
}
// set default labelOne text
override func viewDidLoad() {
super.viewDidLoad()
labelOne.text = "Default passed data"
}
// segue ViewController -> ViewControllerB
override func prepareForSegue(segue: (UIStoryboardSegue!), sender: AnyObject!)
{
if segue.identifier == "viewNext" {
let viewControllerB = segue.destinationViewController as! ViewControllerB
viewControllerB.dataPassed = labelOne.text
}
}
// segue ViewControllerB -> ViewController
@IBAction func unwindToThisView(sender: UIStoryboardSegue) {
if let sourceViewController = sender.sourceViewController as? ViewControllerB {
dataRecieved = sourceViewController.dataPassed
}
}
}
(vcB)
source (notez que le délégué UITextFieldDelegate
ici est uniquement utilisé pour muter "localement" la valeur de la propriété dataPassed
, qui sera retournée à (vcA)
et affecté à dataRecieved
propriété de ce dernier)
/* ViewControllerB.Swift */
import UIKit
class ViewControllerB: UIViewController, UITextFieldDelegate {
var dataPassed : String?
@IBOutlet weak var textField: UITextField!
// set default textField text to the data passed from previous view.
override func viewDidLoad() {
super.viewDidLoad()
textField.text = dataPassed
// Handle the user input in the text field through delegate callbacks
textField.delegate = self
}
// UITextFieldDelegate
func textFieldShouldReturn(textField: UITextField) -> Bool {
// User finished typing (hit return): hide the keyboard.
textField.resignFirstResponder()
return true
}
func textFieldDidEndEditing(textField: UITextField) {
dataPassed = textField.text
}
}
Exemple d'exécution:
Voici comment je le ferais:
Créez une sortie dans le contrôleur de vue 1, comme ceci:
@IBAction func unwindToViewController1(segue: UIStoryboardSegue) {
let foo = segue.sourceViewController.foo
// TODO: Use foo in view controller 1
}
Connectez le contrôleur d'affichage 2 (le vc à partir duquel vous vous déroulez) comme indiqué ci-dessous. Faites glisser du cercle jaune dans vc2 vers "Quitter". L'IBAction du contrôleur de vue 1 devrait apparaître. Sélectionnez-le.
Maintenant, chaque fois que vous vous détendez du contrôleur de vue 2, le unwindToViewController1:
la méthode dans le contrôleur de vue 1 sera appelée.
C'est là que vous récupérerez la propriété que vous souhaitez du contrôleur de vue 2. Notez que vous devez convertir le segue.sourceViewController
à votre sous-classe de contrôleur de vue personnalisé afin d'obtenir la bonne propriété.
Si votre application prend en charge iOS 9+, vous pouvez transmettre des données presque de la même manière que prepareForSegue, utilisez IStoryboardUnwindSegueSource qui a une propriété sender qui est exactement la même que la sender
propriété dans prepare (pour segue: UIStoryboardSegue, sender: Any?) .
Comment l'utiliser:
Remarque: La connexion de la méthode unwindTo est identique à @ Øyvind Hauge et @dfri expliquées dans leurs réponses.
fromViewController
est le type dont vous veniezsender
au type que vous avez envoyé et retournez trueCapture de code (Swift 4.0):
@IBAction func unwindToMyFirstViewController(segue: UIStoryboardSegue) {}
override func canPerformUnwindSegueAction(_ action: Selector, from fromViewController: UIViewController, withSender sender: Any) -> Bool {
if fromViewController is MyCustomViewController,
let customType = sender as? MyCustomType {
return true
}
return false
}