Passing Data in Swift

前端 未结 3 825
遇见更好的自我
遇见更好的自我 2020-12-07 22:06

I have been looking for an answer for this, but have only found answers for segues.

I have viewController1 with a button that segues to viewContr

相关标签:
3条回答
  • 2020-12-07 22:40

    There are two common patterns, both of which eliminate the need for viewController2 to know explicitly about viewController1 (which is great for maintainability):

    1. Create a delegate protocol for your for viewController2 and set viewController1 as the delegate. Whenever you want to send data back to viewController1, have viewController2 send the "delegate" the data

    2. Setup a closure as a property that allows passing the data. viewController1 would implement that closure on viewController2 when displaying viewController2. Whenever viewController2 has data to pass back, it would call the closure. I feel that this method is more "swift" like.

    Here is some example code for #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)
                    }
                }
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-07 22:40

    I used the code from the first answer in a transition between controllers WITHOUT prepareForSegue and worked for me as well. Here's the sample code.

    The First View Controller:

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

    The second View Controller:

    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) 
    }
    
    0 讨论(0)
  • 2020-12-07 22:45

    (Swift 2.1, Xcode 7, iOS9) If you don't want it to be tightly coupled only between 2 ViewControllers, You can also use the Notification Design Pattern (Post & Observe), which is mainly used to pass on the same object/information from one VC to multiple View Controllers.

    For your scenario : In VC2.swift :

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

    And in 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
        }
         }
    

    Common Practise is:

    1. Pass data forward -> Use PrepareForSegue
    2. Pass data backward to the previous View Controller-> Protocol and Delegation
    3. Pass data across multiple View Controllers -> Notifications : Post and Observe(observe in all the View controllers where you are using the object details)
    0 讨论(0)
提交回复
热议问题