2016-02-10 8 views
20

Ho creato due controller di vista. Ho creato un seguito dal primo al secondo per passare i dati. Ora voglio passare i dati dal secondo controller della vista al primo. Ho affrontato molte domande simili e non sono in grado di implementarle perché mi manca la conoscenza di come funziona lo svolgimento.Passare i dati con i successivi di svolgimento

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

Ciò passerà i dati dataPassed in vista del regolatore "viewControllerB". Dire, ora voglio passare alcuni dati da viewControllerB ai dati ricevuti in ViewController. Come posso fare questo con solo unwind segue e non usando delegate. Sono abbastanza nuovo da fare, apprezzerei una spiegazione dettagliata.

+0

È sufficiente implementare 'prepareForSegue' nel controller di visualizzazione unwinding e accedere a' destinationViewController', che sarà il controller di visualizzazione a cui ci si sta svolgendo. Probabilmente vorrai dare lo svolgimento e l'identificatore allo svolgimento nello storyboard – Paulw11

+0

Viene visualizzato un messaggio di errore "non ha seguito con identificatore" btnSubmitSegue "". Ho aggiunto l'identificatore dei passaggi nel controller della vista. Sto usando solo un seguito per collegare entrambi i controller della vista. Credo che il riavvolgimento segua solo il precedente controller di visualizzazione senza ulteriori passaggi? Puoi spiegare in dettaglio?Un po 'di codice sarebbe apprezzato :) – ebby94

+0

Si crea il percorso di svolgimento come di consueto - trascinare sull'icona' uscita 'nella scena. Ora nella finestra di ispezione dell'oggetto a sinistra vedrai le fasi di svolgimento elencate sotto il controller di visualizzazione, il primo risponditore e le icone di uscita. Puoi cliccare sul seguente svolgimento e assegnargli un identificatore nell'ispettore a destra. – Paulw11

risposta

43

Øyvind Hauge mi ha battuto alla stessa soluzione metodo, ma come avevo già iniziato con una risposta più dettagliata, ti inserirlo pure.


Diciamo che il vostro due controller di vista sono denominati come segue:

  • punto di master/ingresso: ViewController(vcA)
  • vista secondario: ViewControllerB(vcB)

si imposta l'segue da (vcA) -> (vcB) come hai fatto nell'esempio

/* 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 
    } 
} 

Il passo alquanto difficile è poi che, con questo metodo, la segue utilizzato per passare dati indietro da(vcB)a(vcA) è anche aggiunti alla fonte di (vcA), come metodo @IBAction (piuttosto che, come potrebbe essere previsto, aggiunto alla fonte di (vcB)).

/* in ViewController.swift */ 

// ... 

// segue ViewControllerB -> ViewController 
@IBAction func unwindToThisView(sender: UIStoryboardSegue) { 
    if let sourceViewController = sender.sourceViewController as? ViewControllerB { 
     dataRecieved = sourceViewController.dataPassed 
    } 
} 

È da allora in poi collegare ad esempio, un pulsante in (vcB) a questa azione rilassarsi nel (vcA) via manuale Exit segue in (vcB):

enter image description here

Seguono un esempio completo di passare il testo da (vcA) a (vcB); (eventualmente) modificando quel testo tramite UITextField, restituendo infine il testo (eventualmente) modificato a (vcA).


(vcA) fonte:

/* 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) fonte (notare che il UITextFieldDelegate delegato qui viene utilizzato solo per "localmente" mutare il valore della proprietà dataPassed, che verrà restituita al (vcA) e assegnato a dataRecieved proprietà di quest'ultimo)

/* 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 
    } 
} 

esecuzione Esempio:

enter image description here

+0

Grazie mille per la spiegazione dettagliata! Questo mi ha aiutato a capire meglio :) – ebby94

+0

Forse è proprio di fronte a me ma cos'è "newValue" in "setSet { labelOne.text = newValue }" –

+0

@DarkhorseFantasySports nessun problema: è un nome predefinito per il nuovo valore da set: _ "Se si implementa un osservatore' willSet', viene passato il nuovo valore della proprietà come parametro costante.È possibile specificare un nome per questo parametro come parte dell'implementazione 'willSet'. Se non si scrive il nome del parametro e parentesi all'interno della tua implementazione, il parametro è reso disponibile con un nome di parametro predefinito di 'newValue'." _ - Da [la Guida Swift Language - Proprietà] (https://developer.apple.com/library/content/documentation/ Swift/concettuale/Swift_Programming_Language/Properties.html). – dfri

7

Ecco come lo farei:

  1. Creare una presa in vista del regolatore 1, in questo modo:

    @IBAction func unwindToViewController1(segue: UIStoryboardSegue) { 
    
        let foo = segue.sourceViewController.foo 
    
        // TODO: Use foo in view controller 1 
    } 
    
  2. Collegare controller della vista 2 (il VC si sta svolgimento da) come mostrato di seguito. Trascina dal cerchio giallo in vc2 a 'Esci'. L'IBAction dal controller di visualizzazione 1 dovrebbe apparire. Selezionalo enter image description here

  3. Ora, ogni volta che si rilassarsi alla vista controllore 2, il metodo unwindToViewController1: in vista del regolatore 1 verrà chiamato.

  4. Qui è dove si recupera la proprietà desiderata dal controller di visualizzazione 2. Si noti che è necessario eseguire il cast dello segue.sourceViewController nella sottoclasse del controller di visualizzazione personalizzato per ottenere la proprietà corretta.

+0

Grazie! Questo ha risposto alla mia domanda :) – ebby94

+0

Felice che abbia funzionato –

0

Se l'applicazione supporta iOS 9+ è possibile passare i dati quasi la stessa di prepareForSegue, utilizzare UIStoryboardUnwindSegueSource che ha una proprietà sender che è esattamente la stessa della proprietà sender in prepare(for segue: UIStoryboardSegue, sender: Any?).

come usarlo:

  1. Creare un metodo unwindTo.

Nota: Collegamento il metodo unwindTo è lo stesso @ Øyvind Hauge e @dfri spiegato nelle loro risposte.

  1. All'interno del controller della vista che si desidera rilassarsi a, l'override del metodo canPerformUnwindSegueAction(_:from:withSender:)
  2. All'interno di questo metodo, verificare se il tipo di fromViewController è il tipo che venivi da
  3. Se esso è, gettato la proprietà sender al tipo che hai inviato e tornare vero
  4. Else, return false

snip Codice (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 
} 
Problemi correlati