Tom Xue Tom Xue - 5 months ago 43
Swift Question

How to Pass Data from View Controllers?

I want to pass a latitude data and longitude data to another controller called DestinationViewController. DestinationViewController contains a map view, so as user transitions to a new view, they will see a flyover map based on the location(latitude and longitude) data in the first view.

Now there is a few problems which I will explain along the way.

FIRST VIEW

import UIKit
import MapKit
import CoreLocation

class SliderViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {


@IBOutlet weak var slider: UISlider!
private var latitude : [Double]!
private var longtitude : [Double]!
override func viewDidLoad() {
sliderSlides(self)

}

@IBAction func sliderSlides(sender: AnyObject) {

let userChoice = Double(self.slider.value)

var realLatlong = [double]()
if userChoice == 1 {
realLatlong = [40.7484405, -73.9856644]
} else if possibility == 2 {
realLatlong = [42.7484405, -4.9856644]
} else {
realLatlong = [50.7484405, -7.9856644]

}


latitude = [realLatlong[0]]
longitude = [realLatlong[1]]



NO error now, completely fine


}

override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "sendLocationdata") {
var destination: DestinationViewController = segue.destinationViewController
as! DestinationViewController



SIGABART


destination.latitude = latitude
destination.longtitude = longitude


}
}


}

DestinationViewController

import UIKit
import MapKit
import CoreLocation

class DestinationViewController: UIViewController, MKMapViewDelegate {

var latitude : Float!
var longtitude : Float!
let distance: CLLocationDistance = 700
let pitch: CGFloat = 65
let heading = 90.0
var camera = MKMapCamera()
var coordinate: CLLocationCoordinate2D!



@IBOutlet var flyoverView: MKMapView!

override func viewDidLoad() {
super.viewDidLoad()
coordinate = CLLocationCoordinate2D(latitude: latitude,
longitude: longitude)



No error at all


flyoverView.mapType = .SatelliteFlyover

camera = MKMapCamera(lookingAtCenterCoordinate: coordinate,
fromDistance: distance,
pitch: 0,
heading: 0)
self.flyoverView.camera = camera

// Do any additional setup after loading the view.
}


override func viewDidAppear(animated: Bool) {
let pitchedCamera = MKMapCamera(lookingAtCenterCoordinate: coordinate, fromDistance: distance, pitch: pitch, heading: 0)
let rotatedCamera = MKMapCamera(lookingAtCenterCoordinate: coordinate, fromDistance: distance, pitch: pitch, heading: 180)

UIView.animateWithDuration(5.0, animations: {
self.flyoverView.camera = pitchedCamera

}, completion: {
(Completed: Bool) -> Void in

UIView.animateWithDuration(25.0, delay: 0, options: UIViewAnimationOptions.CurveLinear, animations: {
self.flyoverView.camera = rotatedCamera
}, completion: nil)

})

}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}


/*
// MARK: - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/

}


Please help me. Leave a comment if you need more information, thanks!

Sam Sam
Answer

For your first error, latitude and longitude are variables in the scope of the sliderSlides function, meaning they exist only within that function. This is why you can't access them from your prepareForSegue. Make them class functions so that they exist in the scope of the class by declaring them outside of any function (I would suggest under your IBOutlet).

It should be like so:

@IBOutlet weak var slider: UISlider!

private var latitude:Double!
private var longitude:Double!

Then when you set them, instead of creating a new variable with let, just change the existing class variable:

latitude = realLatlong[0]

You should be able to access them now in your prepareForSegue.

Note also: Either give them an initial value like so:

private var latitude:Double = 0.0 //Or some default number

or check whether it is nil in prepareForSegue, because currently they will only get set if the sliderSlides function gets called.

For your second error:

You can't use your instance variables(latitude and longitude) to define another instance variable (coordinate). You should declare coordinate as a class variable, but not set its value until the view is loaded.

Replace:

let coordinate = CLLocationCoordinate2D(latitude: latitude,
                                        longitude: longitude)

with:

var coordinate: CLLocationCoordinate2D!

and then in your viewDidLoad add:

coordinate = CLLocationCoordinate2D(latitude: latitude,
                                    longitude: longitude)

If you really don't want to initialise the coordinate in the viewDidLoad you can also do:

var coordinate: CLLocationCoordinate2D {
    get {
        return CLLocationCoordinate2D(latitude: latitude,
                                    longitude: longitude)
    }
}

However I would highly suggest against this as you will be creating a new CLLocationCoordinate2D variable every time you call coordinate. Note also that this will update the coordinate value (in future use) whenever you change latitude and longitude

Also note: latitude and longitude shouldn't be of type Int (as you are requiring the use of the decimal points)

UPDATE:

Addressing your latest code update here because it is easier than in the comments:

In your SliderViewController change:

private var latitude : [Double]!
private var longtitude : [Double]!

to

private var latitude : Double!
private var longtitude : Double!

Because latitude and longitude are single variables, not arrays.

In the sliderSlides function change:

latitude = [realLatlong[0]]
longitude = [realLatlong[1]]

to

latitude = realLatlong[0]
longitude = realLatlong[1]

Because again, they are single values, not arrays.

Then in your DestinationViewController, change:

var latitude : Float!
var longtitude : Float!

to

var latitude : Double!
var longtitude : Double!

Because we need Double values, not Float values

Comments