Casting MKOverlay to MKPolyline return null - ios

I use the following delegate method to draw route on Map. It works fine most of the time except in one route that has large coordinates array. Sometimes it can cast the MKOverlay to MKPolyline and sometimes it cannot for the same route. Any idea why this is happening?
public override MKOverlayView GetViewForOverlay (MKMapView mapView, IMKOverlay overlay)
{
if (overlay is MKPolyline) {
MKPolyline polyline = overlay as MKPolyline;
MKPolylineView polylineView = new MKPolylineView (polyline);
polylineView.StrokeColor = UIColor.Blue;
polylineView.LineWidth = 5.0f;
return polylineView;
}
return null;
}

This code for Objective C and Translate it. Draw route polyLine on map as below code,
func mapView(mapView: MKMapView!, rendererForOverlay overlay: MKOverlay!) -> MKOverlayRenderer! {
if overlay is MKPolyline {
var polylineRenderer = MKPolylineRenderer(overlay: overlay)
polylineRenderer.strokeColor = UIColor.blueColor()
polylineRenderer.lineWidth = 5
return polylineRenderer
}
return nil
}

MKOverlayRenderer GetOverlayRenderer(MKMapView mapView, IMKOverlay overlayWrapper)
{
var type = overlayWrapper.GetType();
var overlay = overlayWrapper as IMKOverlay;
if (overlay is MKPolyline || type == typeof(MKPolyline))
{
if (polylineRenderer == null)
{
polylineRenderer = new MKPolylineRenderer(overlay as MKPolyline);
polylineRenderer.FillColor = UIColor.Blue;
polylineRenderer.StrokeColor = UIColor.Red;
polylineRenderer.LineWidth = 3;
polylineRenderer.Alpha = 0.4f;
}
return polylineRenderer;
}
}
I have the same problem, but this code works on the Simulator but not on a device.

Related

Polylines are disappearing when zoom closely

I created seven different polylines. However some of them are disappearing when I zoom in closely. Why it is happening? How can I prevent this?
Here is my polyline renderer:
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
let renderer = MKPolylineRenderer(polyline: overlay as! MKPolyline)
renderer.strokeColor = UIColor(red: 1, green: 1, blue: 1, alpha: 0.9)
renderer.lineWidth = 2.2
return renderer
}
//Thousands of parameters sending as a parameter
func createPathWithPoints(_ points: [MKMapPoint]) {
let arc = MKPolyline(points: points, count: points.count)
mapView.addOverlay(arc)
}
Please help!
I had similar problem with using MKPolyline and below is what I did to fix this.
1) Make sure that you have your mapView delegate in viewDidLoad().
mapView.delegate = self
2) Add your overlay to the map.
mapView.addOverlay(polyLine())
I am using coredata in my project, so if myLocations are empty then I return empty MKPolyline()
private func polyLine() -> MKPolyline {
guard let locations = myLocations else {
return MKPolyline()
}
// Coordinates
let coords: [CLLocationCoordinate2D] = locations.map { location in
let location = location as! Location
return CLLocationCoordinate2D(latitude: location.latitude, longitude: location.longitude)
}
return MKPolyline(coordinates: coords, count: coords.count)
}
3) We have access to rendererFor from MKMapViewDelegate. You can change color and width for polyline.
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
guard let polyline = overlay as? MKPolyline else {
return MKOverlayRenderer(overlay: overlay)
}
// Setup renderer
let renderer = MKPolylineRenderer(polyline: polyline)
renderer.strokeColor = .systemBlue
renderer.lineWidth = 3
return renderer
}

How do i add dashed polyline in swift 4?

i already have a polyline in Swift4, how can i make the style of it to Dashed/Dotted line ??
let path = GMSMutablePath(path: GMSPath())
for marker in markerList {
bounds = bounds.includingCoordinate(marker.position)
path.add(marker.position)
}
let polyline = GMSPolyline(path: path)
polyline.strokeColor = UIColor(named: "Primary")!
polyline.strokeWidth = 3.0
polyline.geodesic = true
polyline.map = mapView
Like this map
You need to implement func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer delegate method and using renderer.lineDashPhase and renderer.lineDashPattern properties you should be able to achive what you need
code example
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
let renderer = MKPolylineRenderer(overlay: overlay)
renderer.strokeColor = UIColor.red
renderer.lineWidth = 4.0
renderer.lineDashPhase = 2
renderer.lineDashPattern = [NSNumber(value: 1),NSNumber(value:5)]
return renderer
}
result

Changing the stroke color of map overlay on tap

I have a map view and I am generating a bunch of mkcircle overlays. These have a stroke width and fill color.
I also have a tap gesture set up that determines if the tap is on one of the mkcircles. What I would like to do now is change the stroke width and fill color so the user knows which mkcircle was tapped and then change it back on any other tap.
The code I have is below.
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
let circleRenderer = MKCircleRenderer(overlay: overlay)
circleRenderer.fillColor = UIColor.blue.withAlphaComponent(0.1)
circleRenderer.strokeColor = UIColor.blue
circleRenderer.lineWidth = 2
return circleRenderer
}
func handleMapTap(_ gestureReconizer: UITapGestureRecognizer) {
let tapPoint = gestureReconizer.location(in: mapView)
let tapCoordinate = mapView.convert(tapPoint, toCoordinateFrom: mapView)
let point = MKMapPointForCoordinate(tapCoordinate)
if mapView.overlays.count > 0 {
for overlay: MKOverlay in polygonArray {
if (overlay is MKCircle) {
let circle = overlay
let circleRenderer = (mapView.renderer(for: circle) as! MKCircleRenderer)
let datapoint = circleRenderer.point(for: point)
circleRenderer.invalidatePath()
if circleRenderer.path.contains(datapoint) {
let circleIndex = polygonArray.index{$0 === circle}!
print(circleIndex)
}
}
}
}
}
I have done some searching but I have not been able to find a solution yet. I am able to get the circleIndex of the tapped circle.
Any guidance is appreciated.
Just in case anyone else comes across this here is the answer which was actually pretty easy in the end.
func handleMapTap(_ gestureReconizer: UITapGestureRecognizer) {
let tapPoint = gestureReconizer.location(in: mapView)
let tapCoordinate = mapView.convert(tapPoint, toCoordinateFrom: mapView)
let point = MKMapPointForCoordinate(tapCoordinate)
if mapView.overlays.count > 0 {
for overlay: MKOverlay in polygonArray {
if (overlay is MKCircle) {
let circle = overlay
let circleRenderer = (mapView.renderer(for: circle) as! MKCircleRenderer)
let datapoint = circleRenderer.point(for: point)
circleRenderer.invalidatePath()
circleRenderer.fillColor = UIColor.blue.withAlphaComponent(0.1)
circleRenderer.strokeColor = UIColor.blue
if circleRenderer.path.contains(datapoint) {
circleRenderer.fillColor = UIColor.black
circleRenderer.strokeColor = UIColor.black
let circleIndex = polygonArray.index{$0 === circle}!
print(circleIndex)
}
}
}
}
}

MapKit overlay does not appear

I'm trying to add a circle overlay to my map. I followed the apple docs and got this far, but the overlay doesn't appear when I run the app. Here's my code...
#IBOutlet var map: MKMapView!
let location = CLLocationCoordinate2DMake(40.73085, -73.99750)
let regionRadius: CLLocationDistance = 5500
func mapView(mapView: MKMapView, rendererForOverlay overlay: MKOverlay) -> MKOverlayRenderer {
let diskRenderer: MKCircleRenderer = MKCircleRenderer.init()
diskRenderer.fillColor = UIColor.init(red: 0, green: 192, blue: 295, alpha: 1)
return diskRenderer
}
override func viewDidLoad() {
super.viewDidLoad()
let coordinateRegion = MKCoordinateRegionMakeWithDistance(location, regionRadius, regionRadius)
map.setRegion(coordinateRegion, animated: true)
let diskOverlay: MKCircle = MKCircle.init(centerCoordinate: location, radius: 5000)
map.addOverlay(diskOverlay)
// Do any additional setup after loading the view.
}
I'm teaching myself all this stuff so forgive me if i've made an obvious mistake.
See the accepted answer to this question:
How to create MKCircle in Swift?
Steps are:
Ensure this controller implements MKMapViewDelegate:
class YourViewController: UIViewController, MKMapViewDelegate
In viewDidLoad set the delegate on map to self:
override func viewDidLoad() {
super.viewDidLoad()
map.delegate = self;`
Add the following function to render the overlay (change the color, etc):
func mapView(mapView: MKMapView, rendererForOverlay overlay: MKOverlay) -> MKOverlayRenderer {
if let overlay = overlay as? MKCircle {
let circleRenderer = MKCircleRenderer(circle: overlay)
circleRenderer.fillColor = UIColor.blueColor()
return circleRenderer
}
else {
return MKOverlayRenderer(overlay: overlay)
}
}
The radius of your circle is too big as it is currently set and the whole map will be blue. Set it to something small, like 1000, so you can see the circle.
objc in a class that is set as a mkmapviewdelegate:
- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id <MKOverlay>)overlay
{
if ([overlay isKindOfClass:[MKPolygon class]]) {
MKPolygon *polygon = (MKPolygon *)overlay;
MKPolygonRenderer *renderer = [[MKPolygonRenderer alloc] initWithPolygon:polygon];
renderer.strokeColor = [UIColor blueColor];
renderer.lineWidth = 5.;
return renderer;
}
return [[MKOverlayRenderer alloc] initWithOverlay:overlay];
}

iOS 7- MKCircleRenderer Not Being Drawn?

Been trying to figure this out for hours. Trying to do something simple: draw a circle overlay on mapview. BLEvent conforms to the MKMapOverLay protocol and has the information needed (radius, coordinates) Yes my view controller has been set as the map view delegate.
In my viewDidLoad..
for (BLEvent *event in self.model.events) {
[self.mapView addOverlay:event];
}
- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id < MKOverlay >)overlay{
if ([overlay isKindOfClass:[BLEvent class]]){
BLEvent *event = (BLEvent *)overlay;
MKCircle *circle = [MKCircle circleWithCenterCoordinate:event.coordinate radius:event.radius];
MKCircleRenderer *circleR = [[MKCircleRenderer alloc] initWithCircle:circle];
circleR.fillColor = [UIColor blueColor];
return circleR;
} else{
return nil;
}
}
I checked with this, and the renderer was in fact called> I know the coordinates are valid because I had annotations that showed in the map.
- (void)mapView:(MKMapView *)mapView didAddOverlayRenderers:(NSArray *)renderers{
NSLog(#"%#", ((MKCircleRenderer *)[renderers objectAtIndex:0]).fillColor);
}
The circle is not drawn because the MKCircle you create is not added as overlay to the map.
In order to make this work your BLEvent class needs to be a MKCircle subclass.
Then try this:
- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id < MKOverlay >)overlay{
if ([overlay isKindOfClass:[BLEvent class]]){
BLEvent *event = (BLEvent *)overlay;
MKCircleRenderer *circleR = [[MKCircleRenderer alloc] initWithCircle:event];
circleR.fillColor = [UIColor blueColor];
return circleR;
}
return nil;
}
A working version for iOS 8.0 and SWIFT
import Foundation
import MapKit
class MapViewController: UIViewController, CLLocationManagerDelegate, MKMapViewDelegate{
var locationManager: CLLocationManager = CLLocationManager()
#IBOutlet var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
// We use a predefined location
var location = CLLocation(latitude: 46.7667 as CLLocationDegrees, longitude: 23.58 as CLLocationDegrees)
addRadiusCircle(location)
}
func addRadiusCircle(location: CLLocation){
self.mapView.delegate = self
var circle = MKCircle(centerCoordinate: location.coordinate, radius: 10000 as CLLocationDistance)
self.mapView.addOverlay(circle)
}
func mapView(mapView: MKMapView!, rendererForOverlay overlay: MKOverlay!) -> MKOverlayRenderer! {
if overlay is MKCircle {
var circle = MKCircleRenderer(overlay: overlay)
circle.strokeColor = UIColor.redColor()
circle.fillColor = UIColor(red: 255, green: 0, blue: 0, alpha: 0.1)
circle.lineWidth = 1
return circle
} else {
return nil
}
}
}

Resources