iOS MKPolygon pattern - ios

I searched over the internet but I couldn't find an answer to this. Is possible to draw polygon filled with some pattern? I don't wanna use 3rd party libraries. I would like to achieve something similar to this:
polygon with pattern

Yes you can do this.
UIColor has an initializer for pattern images.
guard let image = UIImage(named: "Name of the asset") else { return }
let color = UIColor(patternImage: image)
Then in your overlay renderer delegate method, you can simply assign it to your fill color.
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
// Renderer code
yourRenderer.fillColor = color
// Return your renderer
}

Related

Load all tiles for area in mapView

I have found a way to cache tiles with MapKit, but I haven't found any solution for loading all tiles inside an area to from the top level tiles to the bottom level tiles.
I want to cache all tiles for a rectangle area in my mapview. Is there any way to do this in Mapkit?
In order to load custom tiles in MKMapView you need to subclass MKTileOverlay and override method
url(forTilePath path: MKTileOverlayPath) -> URL
MKTitleOverlay contains x, y and z properties for the tile.
So the implementation may look like this:
override func url(forTilePath path: MKTileOverlayPath) -> URL {
let tilePath = Bundle.main.url(
forResource: "\(path.y)",
withExtension: "png",
subdirectory: "tiles/\(path.z)/\(path.x)",
localization: nil)!
return tile
}
In your mapView setting function add the following:
let overlay = CustomTileOverlay()
overlay.canReplaceMapContent = true
mapView.add(overlay, level: .aboveLabels)
Also don't forget to return renderer in
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
return MKTileOverlayRenderer(tileOverlay: overlay)
}
P.S. There is a great tutorial on raywenderlich.com on that subject:

MKOverlay not appearing until MKMapView is zoomed or moved?

So I got an MKCirlce (MKOverlay), and I've added it like this:
self.current_location_overlay = MKCircle(center: self.current_location!, radius: 200)
self.mk_map_view.add(self.current_location_overlay!)
I've set the map delegate and added this MKMapViewDelegate method:
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
if let overlay = overlay as? MKCircle {
let circle_renderer = MKCircleRenderer(circle: overlay)
circle_renderer.fillColor = UIColor.red.withAlphaComponent(0.2)
circle_renderer.setNeedsDisplay()
return circle_renderer
} else {
return MKOverlayRenderer(overlay: overlay)
}
}
Tho the overlay is not appearing at start, only after panning or zooming the map it appears.
Seems like others have had this problem, tho no solution on this post seems to help.
Dose anyone know how to solve this?

MKMapView hide base map layer

I'm trying to draw an MKPolyline using GPS coordinates and show the user's current location along that polyline. However, I do not want to show the base map layer, I'd just like a transparent background.
Is this possible? How can I do this? Swizzling? Third-party? Something else? Everything is in play.
Thanks
Rather than diving through the map view's subviews, I would recommend trying to implement your own MKTileOverlay class with canReplaceMapContent set to YES and fully transparent tiles. My guess is that the map view would simply draw its backgroundColor behind the tiles, and you could set that to clearColor.
There is a pretty good NSHipster article that can get you started.
use empty MKTileOverlay
lazy var mapView: MKMapView = { () -> MKMapView in
let view = MKMapView()
view.mapType = .satellite
view.delegate = self
let overlay = MKTileOverlay()
overlay.canReplaceMapContent = true
view.addOverlay(overlay)
return view
}()
override func loadView() {
self.view = mapView
}
and render
extension ContentViewController: MKMapViewDelegate {
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
return MKOverlayRenderer(overlay: overlay)
}
}
You can do something like,
NSLog(#"mapview background,%#",myMapView.subviews); //here myMapView is MKMapView object!
for (int i = 0; i < myMapView.subviews.count; i++) {
if ([[myMapView.subviews objectAtIndex:i] isKindOfClass:[UIView class]]) {
UIView *tempView = (UIView*)[myMapView.subviews objectAtIndex:i];
tempView.alpha = 0;
}
}
Hope this will help :)

How to overlay an image on a IOS map using swift

I am trying to find out how to overlay an image on a IOS map using SWIFT. I have created the following code that overlays a green circle on a map using map kit. I want to replace the green circle with the rectangular image tOver.png 500,500 I am new to iOS development and to swift. So far I can not find a swift example or good resource.
//
// ViewController.swift
// mapoverlaytest
//
import UIKit
import MapKit
class ViewController: UIViewController,MKMapViewDelegate {
#IBOutlet weak var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
self.mapView.delegate = self;
let location = CLLocationCoordinate2D(
latitude: 51.50007773,
longitude: -0.1246402
)
let span = MKCoordinateSpanMake(0.05, 0.05)
let region = MKCoordinateRegion(center: location, span: span)
mapView.setRegion(region, animated: true)
let annotation = MKPointAnnotation()
annotation.setCoordinate(location)
annotation.title = "Big Ben"
annotation.subtitle = "London"
var overlay = MKCircle (centerCoordinate: location, radius: 500)
mapView.addOverlay(overlay)
mapView.addAnnotation(annotation)
}
func mapView(
mapView: MKMapView!, rendererForOverlay
overlay: MKOverlay!) -> MKOverlayRenderer! {
if (overlay.isKindOfClass(MKCircle))
{
var circleRenderer = MKCircleRenderer(overlay: overlay)
circleRenderer.strokeColor = UIColor.greenColor()
circleRenderer.fillColor = UIColor(
red: 0,
green: 1.0,
blue: 0,
alpha: 0.5)
return circleRenderer
}
return nil
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
As Totem explained, it would be simpler to use an image annotation instead of an overlay if that works for your purposes. It may not work depending on what you want to use this image for, however. The main difference between map overlays and map annotations, is annotations stay the same size when you zoom the map (like a pin), and overlays change with the size of the map (like marking a building). If you want your image to zoom with the map, it gets a little more complicated.
You will want to create a new MKOverlayRenderer subclass to draw your image. You have to draw the image into the image context yourself by subclassing the drawMapRect(mapRect, zoomScale, inContext) function. After you make this subclass, you can just substitute in your custom subclass in place of the MKCircleRenderer, and you should be good to go.
There is a very good write up on Raywenderlich.com, which you should definitely check out. It should walk you through everything you need to know.
Instead of rendererForOverlay, you should implement
func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView!
Inside there, build your MKAnnotationView and set its image property before returning it out. Check out https://developer.apple.com/LIBRARY/ios/documentation/MapKit/Reference/MKAnnotationView_Class/index.html for more info on the MKAnnotationView class.

Is it possible to change Apple Map colors?

I've currently developing an iOS application with a dark theme, and would really like to make the displayed Apple Map also in dark colors.
I've Googled the topic and tried to change the properties of the component through the Storyboard. But, I couldn't find anything.
Is this even possible? Can I change the colors of the Apple Map component... or even just invert the color to make it look dark?
Thank you.
It's a little clumsy and limited, but you could put a UIView with black background color and alpha less than 1.0 (e.g. 0.3) over the map (make sure to turn off user interaction with this view so gestures get passed through to the map) and that would dim the whole thing. A little kludgy and you lose contrast, but it might be worth trying.
You can't do this without using third-party providers like MapBox, at least on iOS 6 and below.
You can create a subclass of MKTileOverlay like
class DarkModeMapOverlay: MKTileOverlay {
init() {
super.init(urlTemplate: nil)
canReplaceMapContent = true
}
override func url(forTilePath path: MKTileOverlayPath) -> URL {
let tileUrl = "https://a.basemaps.cartocdn.com/dark_all/\(path.z)/\(path.x)/\(path.y).png"
return URL(string: tileUrl)!
}
}
and then set the overlay on your MKMapView with
class MapViewController: UIViewController, MKMapViewDelegate {
private var tileRenderer: MKTileOverlayRenderer?
private var mapView: MKMapView {
return view as! MKMapView
}
private func configureTileRenderer() {
let darkModeOverlay = DarkModeMapOverlay()
tileRenderer = MKTileOverlayRenderer(tileOverlay: darkModeOverlay)
mapView.addOverlay(darkModeOverlay, level: .aboveLabels)
}
override func loadView() {
view = MKMapView(frame: .zero)
}
override func viewDidLoad() {
super.viewDidLoad()
mapView.delegate = self
configureTileRenderer()
}
// MARK: MKMapViewDelegate
func mapView(_: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
guard let renderer = self.tileRenderer else {
return MKOverlayRenderer(overlay: overlay)
}
return renderer
}
}

Resources