Передача данных в Swift

Я искал ответ для этого, но нашел ответы только на segues.

У меня есть viewController1 с кнопкой, которая переходит к viewController2. Для этого нет кода, я настроил его через интерфейс. На viewController2 У меня есть кнопка, которая отклоняет себя с помощью

 self.dismissViewControllerAnimated(true, completion, nil)

Я хочу передать строку из viewController2 обратно в viewController1, когда представление отклонено. Как мне это сделать? Кроме того, я использую быстрый.

Спасибо заранее!

Ответы

Ответ 1

Существует два общих шаблона, оба из которых устраняют необходимость в viewController2 явно знать о viewController1 (что отлично подходит для ремонтопригодности):

  • Создайте делегатский протокол для вашего viewController2 и установите viewController1 в качестве делегата. Всякий раз, когда вы хотите отправить данные обратно в viewController1, попросите viewController2 отправить "делегировать" данные

  • Установите закрытие как свойство, которое позволяет передавать данные. viewController1 будет реализовывать это закрытие на viewController2 при отображении viewController2. Всякий раз, когда viewController2 имеет данные для передачи назад, он вызывает закрытие. Я чувствую, что этот метод более "быстрый".

Вот пример кода для # 2:

class ViewController2 : UIViewController {
    var onDataAvailable : ((data: String) -> ())?

    func sendData(data: String) {
        // Whenever you want to send data back to viewController1, check
        // if the closure is implemented and then call it if it is
        self.onDataAvailable?(data: data)
    }
}

class ViewController1 : UIViewController {
   func doSomethingWithData(data: String) {
        // Do something with data
    }
    override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
        // When preparing for the segue, have viewController1 provide a closure for
        // onDataAvailable
        if let viewController = segue.destinationViewController as? ViewController2 {
            viewController.onDataAvailable = {[weak self]
                (data) in
                if let weakSelf = self {
                    weakSelf.doSomethingWithData(data)
                }
            }
        }
    }
}

Ответ 2

Я использовал код из первого ответа при переходе между контроллерами БЕЗ подготовкиForSegue и работал у меня. Здесь пример кода.

Первый контроллер просмотра:

@IBAction func dpAgendaClick(sender:UIBarButtonItem) {
    ///instantiating view controller with identifier
    if let datePickerViewController = storyboard?.instantiateViewControllerWithIdentifier("DatePickerViewController") 
        as? DatePickerViewController {
            ///bring instantiated view controller to front
            self.presentViewController(datePickerViewController, animated: true, completion: nil)
            ///wrapping the data returned
            datePickerViewController.onDataFiltroAvailable = {[weak self]
                (dataFiltro) in
                if let weakSelf = self {
                    ///use dataFiltro here
                }
}

Второй контроллер просмотра:

var onDataFiltroAvailable: ((dataFiltro: String) -> ())?
///private var
var dataFiltro: String = ""
///the returning data is obtained on the datePickerChanged event
@IBAction func datePickerChanged(sender: UIDatePicker) {
    let dateFormatter = NSDateFormatter()
    dateFormatter.dateStyle = NSDateFormatterStyle.ShortStyle
    dateFormatter.dateFormat = "yyyy-MM-dd"
    dataFiltro = dateFormatter.stringFromDate(datePicker.date)
}

///dismiss the controller on button click
@IBAction func dpOkClick(sender: UIButton) {
    ///"returning" the data
    self.onDataFiltroAvailable?(dataFiltro: dataFiltro)
    dismissViewControllerAnimated(true, completion: nil) 
}

Ответ 3

(Swift 2.1, Xcode 7, iOS9) Если вы не хотите, чтобы он был плотно соединен только между 2 ViewControllers, Вы также можете использовать шаблон дизайна уведомлений (сообщение и наблюдение), который в основном используется для передачи одного объекта/информации с одного VC на несколько контроллеров просмотра.

Для вашего сценария: В 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
    }
     }

Общая практика:

  • Передача данных вперед → Использование PrepareForSegue
  • Передача данных назад в предыдущий контроллер просмотра → Протокол и делегирование
  • Передача данных через несколько контроллеров просмотра → Уведомления: сообщение и наблюдение (см. во всех контроллерах View, в которых вы используете детали объекта)