Передача данных с раскруткой
Я создал два контроллера представления. Я создал переход от первого ко второму для передачи данных. Теперь я хочу передать данные от второго контроллера представления к первому. Я прошел через много похожих вопросов, и я не могу их реализовать, так как мне не хватает знаний о том, как работает разматывание.
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
}
}
Это передаст данные в dataPassed в контроллере представления "viewControllerB". Скажем, теперь я хочу передать некоторые данные из viewControllerB в dataRecieveed во ViewController. Как я могу сделать это с помощью только размотать Segue, а не с помощью делегата. Я довольно новичок в Swift, был бы признателен за подробное объяснение.
3 ответа
Ойвинд Хауге побил меня тем же методом решения, но, поскольку я уже начал с более подробного ответа, я также добавлю его.
Допустим, ваши два контроллера вида названы так:
- Мастер / точка входа:
ViewController
(vcA)
- Вторичный вид:
ViewControllerB
(vcB)
Вы создали переход от (vcA) -> (vcB)
как вы сделали в вашем примере
/* 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
}
}
Несколько более сложный шаг заключается в том, что с помощью этого метода можно использовать последовательность передачи данных из (vcB)
в (vcA)
также добавлен к источнику (vcA)
как @IBAction
метод (а не, как можно было бы ожидать, добавлен к источнику (vcB)
).
/* in ViewController.swift */
// ...
// segue ViewControllerB -> ViewController
@IBAction func unwindToThisView(sender: UIStoryboardSegue) {
if let sourceViewController = sender.sourceViewController as? ViewControllerB {
dataRecieved = sourceViewController.dataPassed
}
}
Вы после этого подключите, скажем, кнопку в (vcB)
на это раскручивать действие в (vcA)
через руководство Exit
перейти в (vcB)
:
Ниже приведен полный пример передачи текста из (vcA)
в (vcB)
; (возможно) изменение этого текста через UITextField
и, наконец, вернуть (возможно) измененный текст в (vcA)
,
(vcA)
источник:
/* 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)
источник (обратите внимание, что UITextFieldDelegate
делегат здесь используется только для "локального" изменения значения dataPassed
свойство, которое будет возвращено (vcA)
и назначен dataRecieved
собственность последнего)
/* 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
}
}
Пример выполнения:
Вот как я бы это сделал:
Создайте розетку в контроллере представления 1, например так:
@IBAction func unwindToViewController1(segue: UIStoryboardSegue) { let foo = segue.sourceViewController.foo // TODO: Use foo in view controller 1 }
Подключите контроллер вида 2 (с которого вы разматываете), как показано ниже. Перетащите из желтого круга в vc2 на "Выход". Должен появиться IBAction из контроллера вида 1. Выберите это.
Теперь, когда вы отматываетесь от просмотра контроллера 2,
unwindToViewController1:
метод в представлении контроллер 1 будет вызван.Здесь вы получите нужное свойство из контроллера представления 2. Обратите внимание, что вам нужно привести
segue.sourceViewController
к вашему подклассу контроллера представления, чтобы получить правильное свойство.
Если ваше приложение поддерживает iOS 9+, вы можете передавать данные почти так же, как prepareForSegue, используйте UIStoryboardUnwindSegueSource, у которого есть свойство sender, точно такое же, как sender
свойство в подготовке (для передачи: UIStoryboardSegue, отправитель: любой?).
Как это использовать:
- Создать метод unwindTo.
Примечание. Подключение метода unwindTo такое же, как в объяснениях @Øyvind Hauge и @dfri.
- Внутри контроллера представления, к которому вы хотите развернуться, переопределите метод canPerformUnwindSegueAction(_:from:withSender:)
- Внутри этого метода, проверьте, если тип
fromViewController
это тип вы пришли - Если это так, бросьте
sender
свойство к типу, который вы отправили и вернуть true - Иначе вернем ложь
Кодовый фрагмент (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
}