Murph
Murph

Reputation: 103

Swift Mapkit - Move Away From User Location

I want to display user location and the surrounding area, but I also want to allow the user to pan around the area. Right now if I try to scroll somewhere else on the map it automatically takes me back to the base region with the user at the center. How do I stop this? I want to show the initial view with the user in the center, but I want to be able to scroll around too. Thanks in advance you guys are so helpful!

import UIKit import MapKit import CoreLocation

class ViewControllerMain: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {

@IBOutlet weak var mapView: MKMapView!

var locationManager:CLLocationManager!

override func viewDidLoad() {
    super.viewDidLoad()
    locationManager = CLLocationManager()
    locationManager.requestWhenInUseAuthorization()
    locationManager.desiredAccuracy = kCLLocationAccuracyBest
    locationManager.delegate = self
    locationManager.startUpdatingLocation()
    mapView.showsUserLocation = true
    mapView.delegate = self

    let longPress = UILongPressGestureRecognizer(target: self, action: "action:")
    longPress.minimumPressDuration = 1.0
    mapView.addGestureRecognizer(longPress)
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
}

func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
    let regionToZoom = MKCoordinateRegionMake(manager.location.coordinate, MKCoordinateSpanMake(0.01, 0.01))
    mapView.setRegion(regionToZoom, animated: true)
}

Upvotes: 7

Views: 6033

Answers (3)

Jim Wilson
Jim Wilson

Reputation: 1648

This thread had a good example in both Swift and Obj C. Be sure to look for the comment on the answer I've linked to if you use Swift.

After you set that up, use Control Flow within the didUpdateLocations, so that it re-centers the user's location only if the user has not touched the map.

Here is my full code as an example:

@IBOutlet weak var theMap: MKMapView!

// ... 


// This var and the three following functions are used to tell if the map moves because of the user. 
// This is used in the control flow in didUpdateLocations

private var mapChangedFromUserInteraction = false


private func mapViewRegionDidChangeFromUserInteraction() -> Bool {
    let view: UIView = self.theMap.subviews[0] as UIView
    //  Look through gesture recognizers to determine whether this region change is from user interaction
    if let gestureRecognizers = view.gestureRecognizers {
        for recognizer in gestureRecognizers {
            if( recognizer.state == UIGestureRecognizerState.Began || recognizer.state == UIGestureRecognizerState.Ended ) {
                return true
            }
        }
    }
    return false
}

func mapView(mapView: MKMapView, regionWillChangeAnimated animated: Bool) {
    mapChangedFromUserInteraction = mapViewRegionDidChangeFromUserInteraction()
    if (mapChangedFromUserInteraction) {
        // user changed map region
        println("user changed map region")


    }
}

func mapView(mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
    if (mapChangedFromUserInteraction) {
        // user changed map region

        println("user changed map region")


    }
}

// This function is called each time the user moves.  
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {




// Use Control Flow: if the user has moved the map, then don't re-center.
// NOTE: this is using 'mapChangedFromUserInteraction' from above. 

    if mapChangedFromUserInteraction == true {

        // do nothing, because the user has moved the map.

    }

    else {

        // update on location to re-center on the user.

        // set X and Y distances for the span (zoom). This is very zoomed in.
        let spanX = 0.0005
        let spanY = 0.0005

        // Create a region using the user's location, and the zoo. 
        var newRegion = MKCoordinateRegion(center: theMap.userLocation.coordinate, span: MKCoordinateSpanMake(spanX, spanY))

        // set the map to the new region
        theMap.setRegion(newRegion, animated: true)

        }

}

Upvotes: 1

Beichen FU
Beichen FU

Reputation: 31

locationManager.stopUpdatingLocation();

this is all you need at end of locationManager fun, if you are still looking for

Upvotes: 3

Onato
Onato

Reputation: 10221

Your code in didUpdateLocations is resetting the region. You have two options.

  1. Store in an ivar whether or not you have already set the first location. Only if you haven't do you then set the region.

  2. Set a timer that runs for 15 seconds. If the map is moved by the user you reset the timer. When the timer expires you can recenter to the users location.

This will keep the map centred around the user but will enable them to pan around a bit to get some context.

This answer shows how to do it in Objective-C

Upvotes: 6

Related Questions