Przekazywanie danych w Swift

Szukałem odpowiedzi na to, ale znalazłem tylko odpowiedzi na segue.

Mam viewController1 z przyciskiem, który segreguje viewController2. Nie ma do tego kodu, skonfigurowałem go przez Interface builder. Na viewController2 mam guzik, który się wyłącza z

 self.dismissViewControllerAnimated(true, completion, nil)

Chcę przekazać ciąg znaków z viewController2 z powrotem do viewController1, gdy Widok zostanie odrzucony. Jak mam to zrobić? Również używam swift.

Z góry dzięki!

Author: Dharmesh Kheni, 2014-06-20

3 answers

Istnieją dwa wspólne wzorce, z których oba eliminują potrzebę, aby viewcontroller2 wiedział wyraźnie o viewController1 (co jest Świetne dla utrzymania):

  1. Utwórz protokół delegata Dla for viewcontroller2 i ustaw jako delegata viewController1. Gdy chcesz wysłać dane z powrotem do viewController1, niech viewController2 wyśle "delegat" DANE

  2. Ustaw zamknięcie jako właściwość umożliwiającą przekazywanie danych. viewController1 zaimplementuj to zamknięcie na viewController2 podczas wyświetlania viewController2. Ilekroć viewController2 ma dane do przekazania z powrotem, wywoła zamknięcie. Czuję, że ta metoda jest bardziej "szybka" jak.

Oto przykładowy kod dla #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)
                }
            }
        }
    }
}
 42
Author: drewag,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-20 02:04:56

Użyłem kodu z pierwszej odpowiedzi w przejściu między kontrolerami bez preparedforsegue i też mi się udało. Oto przykładowy kod.

Pierwszy Kontroler Widoku:

@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
                }
}

Drugi kontroler widoku:

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) 
}
 1
Author: Pablo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-21 11:28:36

(Swift 2.1, Xcode 7, iOS9) Jeśli nie chcesz, aby był ściśle sprzężony tylko między 2 kontrolerami ViewControllers, Można również użyć wzorca Notification Design Pattern (Post & Observe) , który służy głównie do przekazywania tego samego obiektu/informacji z jednego VC do wielu kontrolerów widoku.

Dla Twojego scenariusza : w VC2.swift:

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

}

I w 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
    }
     }

Powszechną praktyką jest:

  1. przekaż dane do przodu - > Użyj Preparedforsegue
  2. przekaż dane wstecz do poprzedniego kontrolera widoku - > protokół i delegacja
  3. Przekazywanie danych przez wiele kontrolerów widoku - > powiadomienia: Post i obserwuj (obserwuj we wszystkich kontrolerach widoku, w których używasz szczegółów obiektu)
 0
Author: Naishta,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-14 09:49:44