Как передавать информацию Назад в iOS при обращении к Segue с помощью Swift?

У меня есть два контроллера вида: "Один" и "Два". Я перехожу из VC One в VC Two. На VC Two я выбираю некоторые данные, которые храню в массиве. Когда я нажимаю кнопку "Назад" на панели навигации, я хотел бы отправить этот массив обратно в VC One.

Какой лучший способ сделать это с помощью Swift и Storyboards?

Спасибо!

Ответ 1

Если вы представляете модальный вид с помощью кнопок "Готово" и "Отмена" (вроде как сборщик), захват значения во время метода размотки segue, вероятно, будет самым простым.

Учитывая, что вы хотите использовать встроенную кнопку Back на навигационном контроллере, наилучшей практикой, вероятно, будет реализация протокола, который VC One может соответствовать, а затем обновить VC One, как только будут выбраны данные на VC Two. Что-то вроде:

В VCTwo.swift:

protocol VCTwoDelegate {
    func updateData(data: String)
}

class VCTwo : UIViewController {
    var delegate: VCTwoDelegate?
    ...
    @IBAction func choiceMade(sender: AnyObject) {
        // do the things
        self.delegate?.updateData(self.data)
    }
    ...
}

и в VCOne.swift:

class VCOne: ViewController {
    ...
    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if segue.identifier == "VCTwoSegue" {
            (segue.destinationViewController as VCTwo).delegate = self
        }
    }
    ...
}

extension VCOne: VCTwoDelegate {
    func updateData(data: String) {
        self.internalData = data
    }
}

Ответ 2

Вы также можете использовать шаблон дизайна уведомлений (сообщение и наблюдение), который в основном используется для передачи одного объекта/информации с одного VC на несколько контроллеров View.

Для вашего сценария: В VC2.swift:

@IBAction func BackBtn(sender: UIButton) {  
  NSNotificationCenter.defaultCenter().postNotificationName("ThisIsTheMessage", object: nil, userInfo:["ObjectBeingSent":yourObject])

}

И в VC1.swift:

override func viewDidLoad() {
        super.viewDidLoad()
        NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("yourFunction:"), name: "ThisIsTheMessage", object: nil)
    }



func yourFunction(theNotification : NSNotification) {

           if let extractInfo = theNotification.userInfo {
     //code to use the object sent from VC2, by extracting the object details
    }
     }

Ответ 3

Вот мое решение в Swift 3

1) Создайте протокол внутри файла SecondController.swift. Мы предпочтительно создаем протокол, из которого мы будем получать данные.

protocol Protocol {
        func passingDataBack(withString: String)
}   

2) Создайте переменную типа Протокол

var proto: Protocol!

3) Перейдите в файл ViewController.swift и наследуйте протокол, который мы сделали из файла SecondController.swift.

class ViewController: UIViewController, Protocol {

}   

4) Затем мы хотим соответствовать Протоколу, который мы сделали, создав функцию, которую мы сделали

    func passingDataBack(withString: String) {
//        withString will return the value that has been passed from our SecondController class
        self.title = withString

    }

5) Используйте метод prepareForSegue и перейдите к классу SecondController

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        let vc = segue.destination as? SecondController
        vc?.proto = self //This line will instantiate the protocol to our ViewController class
    }

6) Вернитесь к нашему файлу SecondController.swift и используйте метод didSelectRow и передайте наши данные

 override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

    proto.passingDataBack(withString: items[indexPath.row]) //Call the protocol and the function then pass our data.
    _ = self.navigationController?.popViewController(animated: true) //This will pop back to our previous controller.

}

* Важно помнить!!! *

Вы должны установить протокол с контроллера B для создания экземпляра на контроллере A при переключении с контроллера A на контроллер B

В нашем примере мы перешли из ViewController в SecondController. Мы создаем протокол из нашего SecondController, выполняя

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    let vc = segue.destination as? SecondController
    vc?.proto = self //This line will instantiate the protocol to our ViewController class
}

Если вы этого не сделаете, вы получите сообщение об ошибке Thread 001 в этой строке

proto.passingDataBack(withString: items[indexPath.row]) //Call the protocol and the function then pass our data.

Исходный код Github