ios - entre - Pasar datos con desenrollar segue
pasar datos entre view controllers swift (3)
Øyvind Hauge me superó con el mismo método de solución, pero como ya había comenzado con una respuesta más detallada, también la agregaré.
Digamos que sus dos controladores de vista se nombran de la siguiente manera:
-
Maestro / punto de entrada:
ViewController
(vcA)
-
Vista secundaria:
ViewControllerB
(vcB)
Configura el segue desde
(vcA) -> (vcB)
como lo ha hecho en su ejemplo
/* 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
}
}
El siguiente paso un tanto complicado es que, utilizando este método, el segmento utilizado para pasar datos
de
(vcB)
a
(vcA)
también se
agrega a la fuente de
(vcA)
, como un método
@IBAction
(en lugar de, como podría ser posible se espera, agregado a la fuente de
(vcB)
).
/* in ViewController.swift */
// ...
// segue ViewControllerB -> ViewController
@IBAction func unwindToThisView(sender: UIStoryboardSegue) {
if let sourceViewController = sender.sourceViewController as? ViewControllerB {
dataRecieved = sourceViewController.dataPassed
}
}
Posteriormente, conecte, digamos, un botón en
(vcB)
a esta acción de desenrollado en
(vcA)
través del manual
Exit
segue en
(vcB)
:
A continuación sigue un ejemplo completo de pasar texto de
(vcA)
a
(vcB)
;
(posiblemente) modificando ese texto a través de un
UITextField
, finalmente devolviendo el texto (posiblemente) modificado a
(vcA)
.
(vcA)
fuente:
/* 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)
fuente (tenga en cuenta que el delegado
UITextFieldDelegate
aquí solo se usa para mutar "localmente" el valor de la propiedad
dataPassed
, que se devolverá a
(vcA)
y se asignará a la propiedad
dataRecieved
de este último)
/* 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
}
}
Ejecución de ejemplo:
Creé dos controladores de vista. Creé un segue del primero al segundo para pasar datos. Ahora quiero pasar datos del segundo controlador de vista al primero. Revisé muchas preguntas similares y no puedo implementarlas, ya que me falta el conocimiento sobre cómo funciona el desenrollado.
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
}
}
Esto pasará los datos a dataPassed en el controlador de vista "viewControllerB". Digamos, ahora quiero pasar algunos datos de viewControllerB a dataRecieved en ViewController. ¿Cómo puedo hacer esto con solo desconectar segue y no usando delegado? Soy bastante nuevo en Swift, agradecería una explicación detallada.
Así es como lo haría:
-
Cree una salida en el controlador de vista 1, así:
@IBAction func unwindToViewController1(segue: UIStoryboardSegue) { let foo = segue.sourceViewController.foo // TODO: Use foo in view controller 1 }
-
Conecte el controlador de vista 2 (el vc del que se está desenrollando) como se muestra a continuación. Arrastre desde el círculo amarillo en vc2 hasta ''Salir''. El IBAction del controlador de vista 1 debería aparecer. Seleccionarlo
-
Ahora, cada vez que se desconecte del controlador de vista 2, se
unwindToViewController1:
métodounwindToViewController1:
en el controlador de vista 1. -
Aquí es donde recuperará la propiedad que desea del controlador de vista 2. Tenga en cuenta que necesita convertir el
segue.sourceViewController
en su subclase de controlador de vista personalizado para obtener la propiedad correcta.
Si su aplicación es compatible con iOS 9+, puede pasar datos casi de la misma manera que prepareForSegue, use
UIStoryboardUnwindSegueSource
que tiene una propiedad del
sender
que es exactamente la misma que la propiedad del
sender
en
preparación (por ejemplo: UIStoryboardSegue, remitente: ¿Cualquiera?)
.
Cómo usarlo:
- Crea un método unwindTo.
Nota: Conectar el método unwindTo es lo mismo que @ Øyvind Hauge y @dfri explicados en sus respuestas.
- Dentro del controlador de vista en el que desea relajarse, anule el método canPerformUnwindSegueAction(_:from:withSender:)
-
Dentro de este método, verifique si el tipo
fromViewController
es el tipo del que provenía -
Si es así, convierta la propiedad del
sender
al tipo que envió y devuelva verdadero - De lo contrario, devuelve falso
Recorte de código (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
}