iOS 10 heading arrow for MKUserLocation dot

前端 未结 4 2015
谎友^
谎友^ 2020-12-14 02:24

The Maps app in iOS 10 now includes a heading direction arrow on top of the MKUserLocation MKAnnotationView. Is there some way I can add this to

4条回答
  •  天涯浪人
    2020-12-14 03:08

    I also experienced this same issue (needing an orientation indicator without having the map spin around, similar to the Apple Maps app). Unfortunately Apple has not yet made the 'blue icon for heading' API available.

    I created the following solution derived from @alku83's implementation.

    1. Ensure the class conforms to MKViewDelegate
    2. Add the delegate method to add a blue arrow icon to the maps location dot

      func mapView(_ mapView: MKMapView, didAdd views: [MKAnnotationView]) {
          if views.last?.annotation is MKUserLocation {
              addHeadingView(toAnnotationView: views.last!)
          }
      }
      
    3. Add the method to create the 'blue arrow icon'.

      func addHeadingView(toAnnotationView annotationView: MKAnnotationView) {
          if headingImageView == nil {
              let image = #YOUR BLUE ARROW ICON#
              headingImageView = UIImageView(image: image)
              headingImageView!.frame = CGRect(x: (annotationView.frame.size.width - image.size.width)/2, y: (annotationView.frame.size.height - image.size.height)/2, width: image.size.width, height: image.size.height)
              annotationView.insertSubview(headingImageView!, at: 0)
              headingImageView!.isHidden = true
           }
      }
      
    4. Add var headingImageView: UIImageView? to your class. This is mainly needed to transform/rotate the blue arrow image.

    5. (In a different class/object depending on your architecture) Create a location manager instance, with the class conforming to CLLocationManagerDelegate protocol

      lazy var locationManager: CLLocationManager = {
          let manager = CLLocationManager()
          // Set up your manager properties here
          manager.delegate = self
          return manager
      }()
      
    6. Ensure your location manager is tracking user heading data locationManager.startUpdatingHeading() and that it stops tracking when appropriate locationManager.stopUpdatingHeading()

    7. Add var userHeading: CLLocationDirection? which will hold the orientation value

    8. Add the delegate method to be notified of when the heading values change, and change the userHeading value appropriately

      func locationManager(_ manager: CLLocationManager, didUpdateHeading newHeading: CLHeading) {
           if newHeading.headingAccuracy < 0 { return }
      
           let heading = newHeading.trueHeading > 0 ? newHeading.trueHeading : newHeading.magneticHeading
           userHeading = heading
           NotificationCenter.default.post(name: Notification.Name(rawValue: #YOUR KEY#), object: self, userInfo: nil)
          }
      
    9. Now in your class conforming to MKMapViewDelegate, add the method to 'transform' the orientation of the heading image

         func updateHeadingRotation() {
              if let heading = # YOUR locationManager instance#,
                  let headingImageView = headingImageView {
      
                  headingImageView.isHidden = false
                  let rotation = CGFloat(heading/180 * Double.pi)
                  headingImageView.transform = CGAffineTransform(rotationAngle: rotation)
              }
          }
      

提交回复
热议问题