Bill Headrick Bill Headrick - 7 months ago 12
Swift Question

iOS Swift passing data in Seque following NSSUrlSession Completion Handler

I know that there have been many variations of this question ("passing data between views in swift?") asked but I have not been able to find one that is specific to my situation. This worries me because I am afraid that I am not using proper design patterns. I would love suggestions for design patterns as well as tips on how to solve my specific problem.

Problem Background:

I am creating an app that relies on the users location data. The user pushes a button and when they do I take their latitude and longitude and pass it to a singleton instance that runs a NSURLSession to my web hosted API. The API returns a JSON response that my NSURLSession completion handler translates into a NSDictionary object which it then returns to completion handler of my button as well as a status code. If the status code signals that the data received from my web API was good then I want to pass that data to a new view controller via a segue so the new view controller can format and output the info to the user. However, if the status shows that there was an error or w/e I want to output an appropriate message to the user, and keep them on the same map page so they can select a valid location (I haven't implemented this but assume it shouldn't be too difficult).

My problem:

I know when I want to call a segue and I know what NSDictionary object that I want to pass to that segue. I just don't know how to send it.

Here is my code for the button and its completion handler:

// MARK: ACTIONS
@IBAction func scheduleAppointmentButton(sender: UIButton) {
//grab async manager singleton
let theAsyncManager = AsyncManager.sharedAsyncManager
//Send HTTP Request to API to Get all available Appointments
if let lon = selectedPin?.coordinate.longitude, lat = selectedPin?.coordinate.latitude{
theAsyncManager.httpGetAppointments(lat, lon: lon)
{
(appointments, status) -> () in
if(status == "All Good"){
//Want to trigger segue here and send it appointments object
}
}
} else{
//there was an error here getting the lat and lon
}
}


Thanks in advance for any help. Let me know if you need any other information from me.

Answer

I'll assume appointments is the dictionary returned by your API. You should create a property for your view controller where you store the appointments in your completion handler. Then you should call performSegueWithIdentifier:sender. Finally, in prepareForSegue:sender, assign the dictionary to a property of the segue's destinationViewController. Something like:

class YourViewController: UIViewController {

    var appointments: NSDictionary?

    @IBAction func scheduleAppointmentButton(sender: UIButton) {
        //grab async manager singleton
        let theAsyncManager = AsyncManager.sharedAsyncManager
        //Send HTTP Request to API to Get all available Appointments
        if let lon = selectedPin?.coordinate.longitude, lat = selectedPin?.coordinate.latitude{
            theAsyncManager.httpGetAppointments(lat, lon: lon) {
                (appointments, status) -> () in
                if(status == "All Good"){
                    //Want to trigger segue here and send it appointments object
                    self.appointments = appointments

                    // Remember to perform the segue on the main thread
                    dispatch_async(dispatch_get_main_queue(), {
                        self.performSegueWithIdentifier("NameOfYourSegue", sender: nil)
                    })
                }
            }
        } else{
            //there was an error here getting the lat and lon
        }
    }

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        let destination = segue.destinationViewController as! YourDestinationClassName
        destination.appointments = appointments
    }
}