Swift - NSArray as a parameter and calling LocationManager function within a touchesBegan method

198 views Asked by At

I want a method that will find the distance from the device's location when the screen was pressed, to a new location when the device is moved around. If the screen is pressed again in a different location I want the method to start over and find the distance the device moves from that location. Since the iOS simulator can't detect location it's difficult for me to test this, but does my logic seem accurate? Here's the code:

override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
    func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!){
        var currentLocation = locations.first as! CLLocation
        var currentAlt = currentLocation.altitude
        var newLocation = locations.last as! CLLocation
        var newAlt = newLocation.altitude
        var lengthInMeters = newLocation.distanceFromLocation(currentLocation) as Double
        var heightInMeters = abs(newAlt - currentAlt)
        var hypotenuse = sqrt((lengthInMeters*lengthInMeters)+(heightInMeters+heightInMeters))
        self.horizontalText.text = "Horizontal: " + "\(lengthInMeters)" + "m"
        self.verticalText.text = "Vertical: " + "\(heightInMeters)" + "m"
        self.totalText.text = "Total: " + "\(hypotenuse)" + "m"
     }

}

My main question is if this function within a function is a valid use of the locationManager. I'm relatively new to iOS/Swift programming and I'm still not entirely sure if every time the screen is touched that the locations NSArray will re-initialize itself.

1

There are 1 answers

0
Warren Burton On

No; your logic is not accurate. Your function scoping is wrong and your understanding of how the run loop occurs is off.

First off method names in Cocoa frameworks are generally pretty descriptive of what they do so touchesBegan is called when a touch sequence begins and didUpdateLocations is called when location updates happen.

func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) 

is a delegate method for CLLocationManager so assuming this class was set up as the delegate of the location manager it will get called each time a location update occurs.

  1. What you have is this method declared inside your touchesBegan override, which is while it is syntactically legal it will never get called unless you are calling it from within the function yourself.
  2. Your understanding of how the run loop works and what happens when is off. You will not receive calls to didUpdateLocations during touchesBegan

What you need to do is place it at the scope of the class and record the latest location into a class var which you can reference from within your touchesBegan method.

class FooView:UIView,CLLocationManagerDelegate {

    var firstLocation:CLLocation?
    var currentLocation:CLLocation?
    var locationManager = CLLocationManager()

    func commonSetup() {
        locationManager.delegate = self
        locationManager.startUpdatingLocation()
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
        commonSetup()
    }

    required init(coder aDecoder: NSCoder) {
        super.init(coder:aDecoder)
        commonSetup()
    }

    func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!){
        if firstLocation == nil {
            firstLocation = locations.first as? CLLocation
        }
        else {
            currentLocation = locations.first as? CLLocation
        }

    }

    override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {

        if let currentLocation = self.currentLocation,firstLocation = self.firstLocation {
            var currentAlt = currentLocation.altitude
            var firstAlt = firstLocation.altitude
            var lengthInMeters = currentLocation.distanceFromLocation(firstLocation) as Double
            var heightInMeters = abs(firstAlt - currentAlt)
            var hypotenuse = sqrt((lengthInMeters*lengthInMeters)+(heightInMeters+heightInMeters))
            self.horizontalText.text = "Horizontal: " + "\(lengthInMeters)" + "m"
            self.verticalText.text = "Vertical: " + "\(heightInMeters)" + "m"
            self.totalText.text = "Total: " + "\(hypotenuse)" + "m"
        }


    }


}

It looks like what you are trying to do is display the difference between a "first" location and the location when you touch the view.

And yes you can simulate Location both static and moving in the Simulator. Check these menus.

In Xcode

enter image description here

In the simulator

enter image description here