Передача данных с раскруткой

Я создал два контроллера представления. Я создал переход от первого ко второму для передачи данных. Теперь я хочу передать данные от второго контроллера представления к первому. Я прошел через много похожих вопросов, и я не могу их реализовать, так как мне не хватает знаний о том, как работает разматывание.

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. Создайте розетку в контроллере представления 1, например так:

    @IBAction func unwindToViewController1(segue: UIStoryboardSegue) {
    
       let foo = segue.sourceViewController.foo
    
       // TODO: Use foo in view controller 1
    }
    
  2. Подключите контроллер вида 2 (с которого вы разматываете), как показано ниже. Перетащите из желтого круга в vc2 на "Выход". Должен появиться IBAction из контроллера вида 1. Выберите это. введите описание изображения здесь

  3. Теперь, когда вы отматываетесь от просмотра контроллера 2, unwindToViewController1: метод в представлении контроллер 1 будет вызван.

  4. Здесь вы получите нужное свойство из контроллера представления 2. Обратите внимание, что вам нужно привести segue.sourceViewController к вашему подклассу контроллера представления, чтобы получить правильное свойство.

Если ваше приложение поддерживает iOS 9+, вы можете передавать данные почти так же, как prepareForSegue, используйте UIStoryboardUnwindSegueSource, у которого есть свойство sender, точно такое же, как sender свойство в подготовке (для передачи: UIStoryboardSegue, отправитель: любой?).

Как это использовать:

  1. Создать метод unwindTo.

Примечание. Подключение метода unwindTo такое же, как в объяснениях @Øyvind Hauge и @dfri.

  1. Внутри контроллера представления, к которому вы хотите развернуться, переопределите метод canPerformUnwindSegueAction(_:from:withSender:)
  2. Внутри этого метода, проверьте, если тип fromViewController это тип вы пришли
  3. Если это так, бросьте sender свойство к типу, который вы отправили и вернуть true
  4. Иначе вернем ложь

Кодовый фрагмент (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
}
Другие вопросы по тегам