iOS location service and map

CoreLocation (location and geocoding, etc.)

Use steps:

  1. Import CoreLocation Library
  2. Create CLLocationManager object
  3. Request user authorization - the key of NSLocationWhenInUseUsageDescription needs to be added to Info.plist
  4. Set up agent and implement corresponding agent method
  5. Call start positioning method
  6. Call end location method

    import UIKit
    import CoreLocation
    
    class ViewController: UIViewController {
        
        // 1. Create CLLocationManager object
        lazy var locationManger = CLLocationManager()
    
        override func viewDidLoad() {
            super.viewDidLoad()
            // Do any additional setup after loading the view.
            
            // 2. Request user authorization
            locationManger.requestWhenInUseAuthorization()
            // 3. Set agent
            locationManger.delegate = self
            // 4. Call the start location method
            locationManger.startUpdatingLocation()
            
        }
    }
    
    // MARK: - implement corresponding proxy methods
    extension ViewController: CLLocationManagerDelegate {
        func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
            let lastLocation = locations.last!
            print(lastLocation)
            
            // 5. Call the end positioning method
            manager.stopUpdatingLocation()
        }
    }

Continuous location optimization (setting these properties reduces power consumption)

  • Set distance filter

    // Distance filter, when the location changes by at least 10 meters, the proxy method that updates the location will be called
    locationManger.distanceFilter = 10
  • Set positioning accuracy

    // Positioning accuracy
    /*
    * kCLLocationAccuracyBestForNavigation Accuracy as high as possible (for navigation)
    * kCLLocationAccuracyBest              Accuracy as high as possible
    * kCLLocationAccuracyNearestTenMeters  10 Error within meters
    * kCLLocationAccuracyHundredMeters     100m error
    * kCLLocationAccuracyKilometer         Kilometer error
    * kCLLocationAccuracyThreeKilometers   3000 meter error
    */
    locationManger.desiredAccuracy = kCLLocationAccuracyBest

Common properties and methods of CLLocation

  • Latitude and longitude

    let location = lastLocation
    let coordinate = location.coordinate
    // dimension
    print(coordinate.latitude)
    // longitude
    print(coordinate.longitude)
  • Distance between two positions (straight line distance)

    let distance = location.distance(from: location2)

About authorization

  • Authorization during use: only when the application is in the foreground (the main interface of the application is displayed on the screen), can the application use the location service

    // Corresponding to the NSLocationWhenInUseUsageDescription in Info.plist, describe why the location service is used
    locationManger.requestWhenInUseAuthorization()
  • Always authorize: apps can use location-based services even if they are in the background

    // Corresponding to NSLocationAlwaysAndWhenInUseUsageDescription in Info.plist
    locationManger.requestAlwaysAuthorization()

CLGeocoder (geocode)

  • Geocoding (using place names to obtain geographic information)

    CLGeocoder().geocodeAddressString("Shanghai") { (placemarks, error) in
        // Before use, you need to judge the placemarks, error
        // Need to pay attention to the problem of duplicate names
        print(placemarks)
    }
  • Anti geocoding (using latitude and longitude to get location information)

    CLGeocoder().reverseGeocodeLocation(CLLocation(latitude: 31.23727100, longitude: 121.45111100)) { (placemarks, error) in
        // Before use, you need to judge the placemarks, error
        print(placemarks)
    }
  • Note: placemarks are of [clplacemarks] type. You can obtain location information such as detailed address, street address, city name, etc. through their properties

MapKit

MapView

  • use:

    • import MapKit frameworkimport MapKit
    • For storyboard or xib, drag a map kit view from the control library to a view, or use the code to create a MKMapView object to add to the view
  • Show current location on map

    • Get authorization and set the userTrackingMode property

      var locationManager = CLLocationManager()
      locationManager.requestWhenInUseAuthorization()
      
      // Set if you want to use the proxy method, otherwise do not set
      mapView.delegate = self
      
      // case none = 0 // the user's location is not followed
      // Case follow = 1 / / the map follow s the user's location
      // case followWithHeading = 2 // the map follows the user's location and heading
      mapView.userTrackingMode = .follow
    • Use the agent to get the latest location details

      extension MapController: MKMapViewDelegate {
          func mapView(_ mapView: MKMapView, didUpdate userLocation: MKUserLocation) {
              print(userLocation.location)
              
              // You can set the pin information of the user's location here
              //CLGeocoder().reverseGeocodeLocation(userLocation.location!) { (placemarks, error) in
                  //    let placemark = placemarks?.last
                  // The title and sub title of the bubble pop up after being clicked
                  //    userLocation.title = placemark?.locality
                  //    userLocation.subtitle = placemark?.name
              //}
          }
      }
  • Set map type

    // A street map that shows the position of all roads and some road names.
    // case standard = 0 / / standard map with street information, etc
    
    // Satellite imagery of the area.
    // case satellite = 1 / / satellite image
    
    // A satellite image of the area with road and road name information layered on top.
    // case hybrid = 2 / / satellite image with street information
    
    /* These are not useful in China for the time being
    // @available(iOS 9.0, *)
    // case satelliteFlyover = 3
    
    // @available(iOS 9.0, *)
    // case hybridFlyover = 4
    
    // @available(iOS 11.0, *)
    // case mutedStandard = 5
    */
    mapView.mapType = .standard
  • Set the coordinates or display area of map center point

    // Set the center point displayed in the map
    // mapView.centerCoordinate = userLocation.location!.coordinate
    
    // Set the center point and area displayed in the map
    // mapView.region = MKCoordinateRegion(center: userLocation.location!.coordinate, span: MKCoordinateSpan(latitudeDelta: 0.1, longitudeDelta: 0.1))
    
    // Set the center point and displayed area of the map (animated when changing from another area to the set area)
    // This property can be called to zoom in and out the map
    mapView.setRegion(MKCoordinateRegion(center: userLocation.location!.coordinate, span: MKCoordinateSpan(latitudeDelta: 0.1, longitudeDelta: 0.1)), animated: true)
  • Display and hide of extra information or control

    • Compass

      // The display north arrow is true by default. When the user rotates the map, it will be displayed. Click to return to the initial direction
      mapView.showsCompass = true
    • traffic

      // Show traffic
      mapView.showsTraffic = true
    • scale

      // Display scale
      mapView.showsScale = true

Pin

  • Basic use
  1. Custom pin data model class (MKAnnotation protocol is required)
  2. Create pin object
  3. Add a pin to the map

    // 1. User defined pin data model class
    class MyAnnotation: NSObject, MKAnnotation {
        var coordinate: CLLocationCoordinate2D
    
        var title: String?
    
        var subtitle: String?
        
        init(coordinate: CLLocationCoordinate2D, title: String?, subtitle: String?) {
            self.coordinate = coordinate
            self.title = title
            self.subtitle = subtitle
        }
    }
    
    // Write in the method of view controller with MapView
    // 2. Create a pin object
    let annotiton1 = MyAnnotation(coordinate: CLLocationCoordinate2D(latitude: 39.90680600, longitude: 116.39877350), title: "Beijing", subtitle: "Beijing China")
    // 2. Create a pin object
    let annotiton2 = MyAnnotation(coordinate: CLLocationCoordinate2D(latitude: 31.23170600, longitude: 121.47264400), title: "Shanghai", subtitle: "Shanghai China")
            
    // 3. Add the pin to the map
    mapView.addAnnotations([annotiton1, annotiton2])
  • Custom pin view (implement the following proxy method)

    func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
        // If the pin view of the user's position is returned to nil directly, otherwise it will be changed into a custom pin view
        guard !(annotation is MKUserLocation) else {
            return nil
        }
    
        // 1. To get reusable pin views from the cache pool, you need to implement the definition of MyAnnotationView
        let view = mapView.dequeueReusableAnnotationView(
                withIdentifier: "MyAnnotationView") as? MyAnnotationView
        annotationView = view ?? MyAnnotationView(annotation: annotation,
                                                          reuseIdentifier: "MyAnnotationView")
        // 2. Set the properties to be set for MyAnnotationView
        ......
        // Return to custom pin view
        return annotationView
    }

Draw lines on the map

  1. Create start MKMapItem
  2. Create end MKMapItem
  3. Create direction request and set start and end points
  4. Create MKDirections object on request
  5. Calculate route
  6. Add route to map view
  7. Implementing agent methods
let direction = "Shanghai"

CLGeocoder().geocodeAddressString(direction!) { (placemarks, error) in
    
    // 1. Create starting point MKMapItem
    let sourceItem = MKMapItem.forCurrentLocation()
    // 2. Create terminal MKMapItem
    let destinationItem = MKMapItem(placemark: MKPlacemark(placemark: placemarks!.last!))

    // 3. Create direction request and set start and end points
    let request = MKDirections.Request()
    request.source = sourceItem
    request.destination = destinationItem
    request.transportType = .automobile

    // 4. Create MKDirections object according to the request
    let directions = MKDirections(request: request)
    // 5. Calculate route
    directions.calculate { (response, error) in
        guard let response = response else {
            if let error = error {
                print("Error: \(error)")
            }
            return
        }

        response.routes.forEach({ (route) in
            // 6. Add route to map view
            let polyine = route.polyline
            self.mapView.addOverlay(polyine, level: .aboveRoads)
        })
    }
}

// 7. Implementation of agent method
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
    
    let renderer = MKPolygonRenderer(overlay: overlay)
    
    // Set the color of the line
    renderer.strokeColor = .blue
    // Set lineweight
    renderer.lineWidth = 5

    return renderer
}

Navigation (jump to system map)

  1. Create a MKMapItem using the navigation destination
  2. Build options when opening system map (such as navigation mode, map type, etc.)
  3. Call the openMaps method to open the system map
// 0. Navigation destination
let destination = "Shanghai"

CLGeocoder().geocodeAddressString(direction!) { (placemarks, error) in
    // 1. Create a MKMapItem using the navigation destination
    let destinationItem = MKMapItem(placemark: MKPlacemark(placemark: placemarks!.last!))
    
    // 2. Build options when opening system map (such as navigation mode, map type, etc.)
    let options = [MKLaunchOptionsDirectionsModeKey: MKLaunchOptionsDirectionsModeDriving,
                   MKLaunchOptionsMapTypeKey: 0,
                   MKLaunchOptionsShowsTrafficKey: true] as [String : Any]
    
    // 3. Call the openMaps method to open the system map
    MKMapItem.openMaps(with: [destinationItem], launchOptions: options)
}

Tags: iOS

Posted on Wed, 06 May 2020 06:50:36 -0400 by sherone