Swift 2 Mkmapviewdelegate Rendererforoverlay Compiler Warning

Swift 2 MKMapViewDelegate rendererForOverlay compiler warning

Going by what autocomplete suggests the prototype looks like this:

func mapView(mapView: MKMapView, rendererForOverlay overlay: MKOverlay) -> MKOverlayRenderer

And apparently there's nothing you can do about it, except for returning return MKPolylineRenderer() where normally you would return nil.

To me it looks like an implementation bug, because here's what the documentation says about the returned object:

The renderer to use when presenting the specified overlay on the map. If you return nil, no content is drawn for the specified overlay object.

I suggest you create a case for it in Apple's bug report

How can I fix my MKOverlayRenderer now that I'm using Swift 2.0?

func mapView(mapView: MKMapView, rendererForOverlay overlay: MKOverlay) -> MKOverlayRenderer

will only be called for each overlay that you add to your instance of MKMapView.

If you only add an MKPolyline to your mapView, you can be sure that when this delegate function is called, the overlay parameter will be of type MKPolyline. Since this is the case, there is no reason to check if the overlay parameter is an instance of MKPolyline with if overlay is MKPolyline. You can just do this:

func mapView(mapView: MKMapView, rendererForOverlay overlay: MKOverlay) -> MKOverlayRenderer {
let pr = MKPolylineRenderer(overlay: overlay)
pr.strokeColor = self.lightBlue
pr.lineWidth = 14
return pr
}

If you ever add a different type of overlay to your MKMapView, you can do this:

if overlay is MKPolyline {
// return renderer for MKPolyline overlay
return mkPolylineRenderer
} else {
// handle the different type of overlay...
return otherTypeOfOverlayRenderer
}

The Swift compiler is intelligent enough to infer from the if/else block that something will always be returned.

How to create MKCircle in Swift?

Will show step wise approach about how to create a circular overlay on map view using swift 3 with xcode 8.3.3

In your main storyboard file drag map kit view on to the scene(view) of storyboard and create outlet for the same, here i created mapView. Also you want to create overlay dynamically whenever you go for long press on map, so drag Long Press Gesture Recognizer on to the mapView from object libary and then create action method for the same, here i had created addRegion() for the same.

  1. create a global constant for CLLocationManager class so that it can be accessed in every function. And in your viewDidLoad method, add some code for getting authorization from the user.

        import UIKit  
    import MapKit

    class ViewController: UIViewController {

    @IBOutlet var mapView: MKMapView!
    let locationManager = CLLocationManager()

    override func viewDidLoad() {
    super.viewDidLoad()

    locationManager.delegate = self
    locationManager.requestAlwaysAuthorization()
    locationManager.requestWhenInUseAuthorization()
    locationManager.desiredAccuracy = kCLLocationAccuracyBest
    locationManager.startUpdatingLocation()

    }
  2. Add code for generating a circular region whenever you do long press gesture recognizer in your long press gesture recognizer action method addRegion().

        @IBAction func addRegion(_ sender: Any) {  
    print("addregion pressed")
    guard let longPress = sender as? UILongPressGestureRecognizer else {return}

    let touchLocation = longPress.location(in: mapView)
    let coordinates = mapView.convert(touchLocation, toCoordinateFrom: mapView)
    let region = CLCircularRegion(center: coordinates, radius: 5000, identifier: "geofence")
    mapView.removeOverlays(mapView.overlays)
    locationManager.startMonitoring(for: region)
    let circle = MKCircle(center: coordinates, radius: region.radius)
    mapView.add(circle)

    }

Still you won't see circle physically on the map until you render circle on map. for this you need to implement delegate of mapviewdelegate.

        func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {}

  1. To make code look more cleaner you can create extension after last brace where your class ends. One extension contains code for CLLocationManagerDelegate and other for MKMapViewDelegate.

        extension ViewController: CLLocationManagerDelegate {
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    locationManager.stopUpdatingLocation()
    mapView.showsUserLocation = true
    }
    }

you should call locationManager.stopUpdatingLocation() in delegate method so that your battery does not drain out.

        extension ViewController: MKMapViewDelegate {
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
guard let circelOverLay = overlay as? MKCircle else {return MKOverlayRenderer()}

let circleRenderer = MKCircleRenderer(circle: circelOverLay)
circleRenderer.strokeColor = .blue
circleRenderer.fillColor = .blue
circleRenderer.alpha = 0.2
return circleRenderer
}
}

Here we are making the actual circle on the screen.

Final code should look like this.

import UIKit
import MapKit

class ViewController: UIViewController {

@IBOutlet var mapView: MKMapView!
let locationManager = CLLocationManager()

override func viewDidLoad() {
super.viewDidLoad()

locationManager.delegate = self
locationManager.requestAlwaysAuthorization()
locationManager.requestWhenInUseAuthorization()
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.startUpdatingLocation()

}

// MARK: Long Press Gesture Recognizer Action Method

@IBAction func addRegion(_ sender: Any) {
print("addregion pressed")
guard let longPress = sender as? UILongPressGestureRecognizer else {return}

let touchLocation = longPress.location(in: mapView)
let coordinates = mapView.convert(touchLocation, toCoordinateFrom: mapView)
let region = CLCircularRegion(center: coordinates, radius: 5000, identifier: "geofence")
mapView.removeOverlays(mapView.overlays)
locationManager.startMonitoring(for: region)
let circle = MKCircle(center: coordinates, radius: region.radius)
mapView.add(circle)

}

}

extension ViewController: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
locationManager.stopUpdatingLocation()
mapView.showsUserLocation = true
}
}

extension ViewController: MKMapViewDelegate {
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
guard let circelOverLay = overlay as? MKCircle else {return MKOverlayRenderer()}

let circleRenderer = MKCircleRenderer(circle: circelOverLay)
circleRenderer.strokeColor = .blue
circleRenderer.fillColor = .blue
circleRenderer.alpha = 0.2
return circleRenderer
}
}

Xcode 10.1 swift 4.2 operator overloading causing compiler warning: All paths through this function will call itself

When you do left += right, it calls the same function that you were defining. In other words, your operator overload function += ( left: inout CGVector, right: CGVector) will call itself in all times (infinite recursion). You are doing something like

func foo(String: bar) {
foo(bar)
}

But just by replacing foo with +=, which is not logical. Xcode only gives you a warning now though, it is not an error that stops you from compiling. You probably have written this function wrong in the past (but the warning reminding you this was just added to the compiler).

You probably want something like this

public func += ( left:  inout CGVector, right: CGVector) {
left = CGVector(dx: left.dx + right.dx, dy: left.dy + right.dy)
}


Related Topics



Leave a reply



Submit