Mapkit polyline

Mapkit polyline DEFAULT

Adding Overlays to a MapView

Before we start actually coding, let's go over some background information so you understand what you will be doing in this guide.

Adding decorations, annotations, or markers to a map is done through the use of two classes: MKOverlay, and MKOverlayRenderer.

The MKOverlay is used to represent an area on the map. This area can take on many different forms, including various shapes, or even just a single point. There are several concrete classes that confirm to the MKOverlay protocol that are already supplied for you within the MapKit framework. These classes define common shapes. In this tutorial, we will only look at lines and circles but MapKit provides implementations for several shapes, including:

MKPolyline - This is just a basic line. To be more specific it is a shape composed of one or more points that define connecting line segments. In general, the first and last points of a polyline are not connected to each other.

MKPolygon - represents a shape consisting of one or more points that define a closed polygon. This could be anything from a perfect square to a complicated, irregular polygon, so long as the first and last points are connected to each other to create a closed shape.

MKCircle - Simply represents a circular area on a map. This class manages the data that defines the area and is typically used in conjunction with an MKCircleView object, which handles the drawing of the circular area on a map.

MKPointAnnotation - represents a single location of the map. This class can be useful in situations where all you want to do is associate a point on the map with a title.

If you want more flexibility, you can also create your own custom class that implements the MKOverlay protocol. This protocol has two required properties: coordinate and boundingMapRect. Together, these two properties are used to define where the overlay will show up on the map and how large it will be.

The MKOverlayRenderer defines the basic behavior associated with an overlay object and is responsible for actually drawing the visual representation of an overlay object on the map. Again, several concrete instances of overlay renderers are provided by MapKit: one for each of the concrete overlay objects. But if you want to create your own, you just have to make sure that you override the drawMapRect:zoomScale:inContext method, which draws the contents of the overlay.

Alright, that's enough for now. Let's get started.

Sours: https://cuesta-cis-204.dozuki.com/Guide/Adding+Overlays+to+a+MapView/48

Adding polylines to maps in SwiftUI

03 Mar 2021

As of March 2021, SwiftUI has a built-in map view but it’s quite simple, only supporting basic annotations.

Recently I wrote about making use of this map view for my app Personal Best, where I settled on using dots to represent GPS pings as polylines weren’t available.

At the time this felt like a reasonable compromise, but since then I’ve gotten a lot better at SwiftUI and interfacing with UIKit in particular, so I’ve been exploring how to bridge a map view featuring a polyline to SwiftUI.

This simple tutorial will teach you how to make a map view component in SwiftUI that includes a polyline.

It’s based on hackingswithswift.com’s ‘Advanced MKMapView with SwiftUI’ tutorial, which I combined with a StackOverflow answer from Daniel E. Salinas.

View the code for this tutorial on GitHub

Building the basic map view

Add the following code, which will make a basic map that doesn’t include the polyline yet.

At this point, running our code locally just shows a basic map, centered on the region we specified in .

Basic MapView

Adding a polyline

Add a new property to . It’ll accept an array of location coordinates, which will be used to draw the line.

Now add some code to to draw the polyline based on the coordinates:

Finally, add a new function to which will define how the polyline is rendered.

Now, update to provide :

Run the code and now the line is visible.

MapView with polyline

Conclusion and next steps

Today we learned how to bridge from UIKit to SwiftUI and add a polyline to it. This is the most basic implementation possible, but there are lots of ways this could be improved, for example adding customisation of the polyline, making it optional, adding the ability to add other types of annotation, and so on.

If you have any questions or comments, feel free to reach out via Twitter or email. Links to both are in the footer of this page.

View the code for this tutorial on GitHub

Sours: https://codakuma.com/the-line-is-a-dot-to-you/
  1. Moving boxes stock photo
  2. Applique quilts patterns free
  3. Toy poodle baton rouge

MapKit Tutorial: Overlay Views

Update note: Rony Rozen updated this tutorial for Xcode 11 and Swift 5. Chris Wagner and Owen Brown wrote the previous versions of this tutorial.

While MapKit makes it easy to add a map to your app, that alone isn’t very engaging. Fortunately, you can use custom overlay views to make more appealing maps.

In this MapKit tutorial, you’ll create an app that showcases Six Flags Magic Mountain. By the time you’re done, you’ll have an interactive park map that shows attraction locations, ride routes and character locations. This app is for all you fast-ride thrill seekers out there. ;]

Getting Started

Download the starter project by clicking the Download Materials button at the top or bottom of the tutorial. Then, open the project in Xcode.

The starter project includes the map you’ll work with and buttons to toggle the different types of overlays on and off.

Build and run. You’ll see something like this:

ParkView starter project

Note: If you feel like you need a refresher on how to add a map to your app, or want to dive deeper on the basics of working with MapKit, visit MapKit Tutorial: Getting Started.

Once you feel ready, dive right into overlay views.

All About Overlay Views

Before you start creating overlay views, you need to understand two key classes: and .

tells MapKit where you want it to draw the overlays. There are three steps for using this class:

  1. First, create your custom class that implements the protocol, which has two required properties: and . These properties define where the overlay resides on the map and its size.
  2. Then, create an instance of your class for each area where you want to display an overlay. In this app, for example, you’ll create an instance for a roller coaster overlay and another for a restaurant overlay.
  3. Finally, add the overlays to your map view.

At this point, the map knows where it’s supposed to display the overlays. But it doesn’t know what to display in each region.

This is where comes in. Subclassing it lets you set up what you want to display in each spot.

For example, in this app, you’ll draw an image of the roller coaster or restaurant. MapKit expects to present a object, and this class defines the drawing infrastructure used by the map view.

Look at the starter project. In ContentView.swift, you’ll see a delegate method that lets you return an overlay view:

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

MapKit calls this method when it realizes there’s an object in the region the map view is displaying.

To sum up, you don’t add objects directly to the map view. Instead, you tell the map about objects to display and return s when the delegate method requests them.

Now that you’ve covered the theory, it’s time to put these concepts to use!

Adding Your Information to the Map

Currently, the map doesn’t provide enough information about the park. Your task is to create an object that represents an overlay for the entire park.

First, select the Overlays group and create a new Swift file named ParkMapOverlay.swift. Then replace its contents with:

import MapKit class ParkMapOverlay: NSObject, MKOverlay { let coordinate: CLLocationCoordinate2D let boundingMapRect: MKMapRect init(park: Park) { boundingMapRect = park.overlayBoundingMapRect coordinate = park.midCoordinate } }

Conforming to forces you to inherit from . The initializer takes the properties from the passed object, which is already in the starter project, and sets them to the corresponding properties.

Next, you need to create a that knows how to draw this overlay.

Create a new Swift file in the Overlays group called ParkMapOverlayView.swift. Replace its contents with:

import MapKit class ParkMapOverlayView: MKOverlayRenderer { let overlayImage: UIImage // 1 init(overlay: MKOverlay, overlayImage: UIImage) { self.overlayImage = overlayImage super.init(overlay: overlay) } // 2 override func draw( _ mapRect: MKMapRect, zoomScale: MKZoomScale, in context: CGContext ) { guard let imageReference = overlayImage.cgImage else { return } let rect = self.rect(for: overlay.boundingMapRect) context.scaleBy(x: 1.0, y: -1.0) context.translateBy(x: 0.0, y: -rect.size.height) context.draw(imageReference, in: rect) } }

Here’s a breakdown of what you added:

  1. overrides the base method by providing a second argument.
  2. is the real meat of this class. It defines how MapKit should render this view when given a specific , and the of the graphic context, with the intent to draw the overlay image onto the context at the appropriate scale.
Note: The details of Core Graphics drawing are outside the scope of this tutorial. However, you can see the code above uses the passed to get a in which to draw the image in the provided context. To learn more about Core Graphics, check out the Core Graphics tutorial series.

Great! Now that you have both an and , add them to your map view.

Creating Your First Map Overlay

In ContentView.swift, find and change its TODO content to:

let overlay = ParkMapOverlay(park: park) mapView.addOverlay(overlay)

This method adds an to the map view.

Take a look at . You’ll see when a user taps the button in the navigation bar to show the map overlay, is called. Now that you’ve added the necessary code, the overlay displays.

Notice that also removes any annotations and overlays that may be present so you don’t end up with duplicate renderings. This is not necessarily efficient, but it’s a simple approach to clear previous items from the map.

The last step standing between you and seeing your newly implemented overlay on the map is , mentioned earlier. Replace its current TODO implementation with:

if overlay is ParkMapOverlay { return ParkMapOverlayView( overlay: overlay, overlayImage: UIImage(imageLiteralResourceName: "overlay_park")) }

When MapKit determines an is in view, it calls this delegate method to obtain a renderer.

Here, you check if the overlay is of class type . If so, you load the overlay image, create a instance with the overlay image and return this instance to the caller.

There’s one little piece missing, though: Where does that suspicious little image come from? It’s a PNG to overlay the map with the defined park’s boundary. The image, found in Assets.xcassets, looks like this:

mapkit

Build and run, enable the :Overlay: option at the top of the screen and voilà! Here’s the park overlay drawn on top of your map:

ParkView with park overlay

Zoom in, zoom out, and move around. The overlay scales and moves as you would expect. Cool!

Adding Annotations

If you’ve ever searched for a location in the native Maps app, you’ve seen those colored pins appear on the map. These are annotations created with . You can use annotations in your own app and use any image you want, not just pins!

Annotations are useful to help highlight specific points of interest to park visitors. They work similarly to and , but instead you’ll work with and .

Writing Your First Annotation

First, create a new Swift file in the Annotations group called AttractionAnnotation.swift. Then, replace its contents with:

import MapKit // 1 enum AttractionType: Int { case misc = 0 case ride case food case firstAid func image() -> UIImage { switch self { case .misc: return UIImage(imageLiteralResourceName: "star") case .ride: return UIImage(imageLiteralResourceName: "ride") case .food: return UIImage(imageLiteralResourceName: "food") case .firstAid: return UIImage(imageLiteralResourceName: "firstaid") } } } // 2 class AttractionAnnotation: NSObject, MKAnnotation { // 3 let coordinate: CLLocationCoordinate2D let title: String? let subtitle: String? let type: AttractionType // 4 init( coordinate: CLLocationCoordinate2D, title: String, subtitle: String, type: AttractionType ) { self.coordinate = coordinate self.title = title self.subtitle = subtitle self.type = type } }

Here’s what you added:

  1. helps you categorize each attraction into a type. This enum lists four types of annotations: misc, rides, foods and first aid. There’s also a handy method to grab the correct annotation image.
  2. You create this class and make it conform to .
  3. Much like , has a required property. You define a handful of properties specific to this implementation.
  4. Finally, you define an initializer that lets you assign values to each of the properties.

Next, you’ll create a specific instance of to use for your annotations.

Associating a View With Your Annotation

First, create another Swift file called AttractionAnnotationView.swift in Annotations group. Then, replace its contents with the following snippet:

import MapKit class AttractionAnnotationView: MKAnnotationView { // 1 // Required for MKAnnotationView required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) } // 2 override init(annotation: MKAnnotation?, reuseIdentifier: String?) { super.init(annotation: annotation, reuseIdentifier: reuseIdentifier) guard let attractionAnnotation = self.annotation as? AttractionAnnotation else { return } image = attractionAnnotation.type.image() } }

Here’s a code breakdown:

  1. requires . Without its definition, an error prevents you from building and running the app. To avoid this, define it and call its superclass initializer.
  2. You also override and set a different annotation image based on the annotation’s type property.

Now that you’ve created the annotation and its associated view, you can start adding annotations to your map view!

Adding Annotations to the Map

To determine the location of each annotation, you’ll use the info in the MagicMountainAttractions.plist file, which you can find under the Park Information group. The plist file contains coordinate information and other details about the attractions at the park.

Go back to ContentView.swift and replace the TODO: implementation of with:

// 1 guard let attractions = Park.plist("MagicMountainAttractions") as? [[String: String]] else { return } // 2 for attraction in attractions { let coordinate = Park.parseCoord(dict: attraction, fieldName: "location") let title = attraction["name"] ?? "" let typeRawValue = Int(attraction["type"] ?? "0") ?? 0 let type = AttractionType(rawValue: typeRawValue) ?? .misc let subtitle = attraction["subtitle"] ?? "" // 3 let annotation = AttractionAnnotation( coordinate: coordinate, title: title, subtitle: subtitle, type: type) mapView.addAnnotation(annotation) }

Here’s a step by step breakdown:

  1. First, you read MagicMountainAttractions.plist and store it as an array of dictionaries.
  2. Then, you iterate over each dictionary in the array.
  3. For each entry, you create an instance of with the point’s information and add it to the map view.

You’re almost there! Last but not least, you need to implement another delegate method that provides the instances to the map view so it can render them on itself.

Add the following method to the class at the top of the file:

func mapView( _ mapView: MKMapView, viewFor annotation: MKAnnotation ) -> MKAnnotationView? { let annotationView = AttractionAnnotationView( annotation: annotation, reuseIdentifier: "Attraction") annotationView.canShowCallout = true return annotationView }

This method receives the selected and uses it to create the . Since the property is set to , a call-out appears when the user touches the annotation. Finally, the method returns the annotation view.

Build and run to see your annotations in action! Don’t forget to turn on the :Pins: option.

ParkView attraction pins

The Attraction pins are looking rather sharp at this point! :]

So far, you’ve covered several complicated bits of MapKit, including overlays and annotations. But what if you need to use some drawing primitives, like lines and circles?

The MapKit framework also lets you draw directly onto a map view. MapKit provides , and for this purpose. Time to try them out!

I Walk The Line: MKPolyline

If you’ve ever been to Magic Mountain, you know that the Goliath hypercoaster is an incredible ride. Some riders like to make a beeline for it as soon as they walk in the gate! :]

To help these riders out, you’ll plot a path from the entrance of the park straight to the Goliath.

is a great solution for drawing a path that connects multiple points, such as plotting a non-linear route from point A to point B.

To draw a polyline, you need a series of longitude and latitude coordinates in the order they should be plotted. EntranceToGoliathRoute.plist, again found in the Park Information folder, contains the path information.

Now, you need a way to read that plist file and create the route for the riders to follow.

First, open ContentView.swift and find . Then, replace it’s current TODO implementation with:

guard let points = Park.plist("EntranceToGoliathRoute") as? [String] else { return } let cgPoints = points.map { NSCoder.cgPoint(for: $0) } let coords = cgPoints.map { CLLocationCoordinate2D( latitude: CLLocationDegrees($0.x), longitude: CLLocationDegrees($0.y)) } let myPolyline = MKPolyline(coordinates: coords, count: coords.count) mapView.addOverlay(myPolyline)

This method reads EntranceToGoliathRoute.plist and converts the individual coordinate strings to structures.

It’s remarkable how simple it is to implement a polyline: You simply create an array containing all of the points and pass it to ! It doesn’t get much easier than that.

Remember, already calls whenever the user toggles this option via the UI. All that’s left now is for you to update the delegate method so it returns the actual view you want to render on the map view.

Go back to and add this clause to the existing condition:

else if overlay is MKPolyline { let lineView = MKPolylineRenderer(overlay: overlay) lineView.strokeColor = .green return lineView }

The process of displaying the polyline view is very similar to previous overlay views. However, in this case, you don’t need to create any custom view objects. You simply use the provided class and initialize a new instance with the overlay.

also lets you change some of the polyline’s attributes. In this case, you’ve modified the stroke color to show as green.

Build and run your app. Enable the :Route: option and it’ll appear on the screen:

ParkView route

Now Goliath fanatics can make it to the coaster in record time! :]

It would be nice to show the park patrons where the park boundaries are, since the park doesn’t actually occupy the entire space shown on the screen.

You could use to draw a shape around the park boundaries, but MapKit provides another class specifically designed to draw closed polygons: .

Don’t Fence Me In: MKPolygon

is similar to , except the first and last points in the set of coordinates are connected to each other to create a closed shape.

You’ll create an as an overlay that shows the park boundaries. The park boundary coordinates are defined in MagicMountain.plist. Look at in Park.swift to see where the boundary points are read from the plist file.

Now, in ContentView.swift, replace the TODO implementation of with:

mapView.addOverlay(MKPolygon( coordinates: park.boundary, count: park.boundary.count))

Given the boundary array and point count from the park instance, you can quickly and easily create a new instance!

Can you guess the next step here? It’s similar to what you did for .

Yup, that’s right. conforms to like does, so you need to update the delegate method again.

Go back to and add this clause to the existing conditions:

else if overlay is MKPolygon { let polygonView = MKPolygonRenderer(overlay: overlay) polygonView.strokeColor = .magenta return polygonView }

You create an as an instance of and set the stroke color to magenta.

Run the app and enable the :Bound: option to see your new boundary in action. You may have to zoom out so the park boundaries can fit the simulator’s screen bounds.

ParkView boundary

That takes care of polylines and polygons. The last drawing method to cover is drawing circles as an overlay, which you’ll do with .

Circle in the Sand: MKCircle

is also very similar to and , except it draws a circle when given the center coordinate point and a radius that determines the size of the circle.

Many park visitors like to visit with the characters. You can help them find the characters by marking where they were last spotted on the map with circles. The overlay lets you do this easily.

The Park Information folder also contains the character location files. Each file is an array of a few coordinates where the user spotted characters.

First, create a new swift file under the Models group called Character.swift. Then replace its contents with the following code:

import MapKit // 1 class Character: MKCircle { // 2 private var name: String? var color: UIColor? // 3 convenience init(filename: String, color: UIColor) { guard let points = Park.plist(filename) as? [String] else { self.init() return } let cgPoints = points.map { NSCoder.cgPoint(for: $0) } let coords = cgPoints.map { CLLocationCoordinate2D( latitude: CLLocationDegrees($0.x), longitude: CLLocationDegrees($0.y)) } let randomCenter = coords[Int.random(in: 0...3)] let randomRadius = CLLocationDistance(Int.random(in: 5...39)) self.init(center: randomCenter, radius: randomRadius) self.name = filename self.color = color } }

Here’s what this code does:

  1. Character class conforms to protocol.
  2. It defines two optional properties: and .
  3. The convenience initializer accepts a plist filename and color to draw the circle. Then it reads in the data from the plist file and selects a random location from the four locations in the file. Next, it chooses a random radius to simulate the time variance. The returned is set and ready to be put on the map!

Now you need a method to add the characters. So, open ContentView.swift and replace the TODO implementation of with:

mapView.addOverlay(Character(filename: "BatmanLocations", color: .blue)) mapView.addOverlay(Character(filename: "TazLocations", color: .orange)) mapView.addOverlay(Character(filename: "TweetyBirdLocations", color: .yellow))

This method performs pretty much the same operations for each character: It passes the plist filename for each one, decides on a color and adds it to the map as an overlay.

You’re almost done! Do you remember the last step?

Right! You need to give the map view a by using the delegate method.

Go back to and add this clause to the existing conditions:

else if let character = overlay as? Character { let circleView = MKCircleRenderer(overlay: character) circleView.strokeColor = character.color return circleView }

Build and run the app, and enable the :Characters: option to see where everyone is hiding!

ParkView characters

Where to Go From Here?

You can download the complete project by using the Download Materials button at the top or bottom of this tutorial.

Congratulations! You’ve worked with some of the most important capabilities that MapKit provides. With a few basic functions, you’ve implemented a full-blown and practical mapping app complete with annotations and custom overlays.

There are many ways to generate overlays that range from very easy to very complex. The approach taken in this tutorial for the image was the easy, yet tedious, route.

There are much more advanced, and perhaps more efficient, methods to create overlays. For example, you could use KML tiles or other third party provided resources.

To learn more about MapKit, check out the other MapKit tutorials on our site, such as Advanced MapKit Tutorial: Custom Tiles.

I hope you enjoyed this tutorial, and I hope to see you use MapKit overlays in your own apps. If you have any questions or comments, please join the forum discussion below!

raywenderlich.com Weekly

The raywenderlich.com newsletter is the easiest way to stay up-to-date on everything you need to know as a mobile developer.

Get a weekly digest of our tutorials and courses, and receive a free in-depth email course as a bonus!

Sours: https://www.raywenderlich.com/9956648-mapkit-tutorial-overlay-views

Welcome to part 2 of the MapKit tutorial series. If you read part 1 of this tutorial, you should already be familiar with the basics of MapKit. Let’s get started with some of MapKit’s more advanced features!

You can get started by downloading the starter project from GitHub. This starter project is the completed project from part 1 of this tutorial, which you should read if you haven’t done so already.

Creating Polylines

In the last part of this tutorial series, we worked with overlays in MapKit. We rendered overlays on top of the map to show users key areas that we wanted to highlight. By combining annotations and overlays, you can really easily display rich data on top of a map. In our last example, we rendered a circle.

Let’s go ahead and try something more complex. Unlike what we get with , MapKit doesn’t provide any predefined classes for other shapes, so we have to make our own.

How about we start with the basics to create a polyline, or a line made up of multiple different points joined together? To keep things simple, we will draw a polyline between all of the cities we used in the last example. The class we use to draw polylines in MapKit is called , and it’s fairly easy to use. Let’s get started!

is a class that can be used to represent a connected sequence of line segments. You can create a polyline by constructing a MKPolyline object with a series of end-points like this:

map-route-3

First, head to , where all of the magic related to our map is taking place. Then, move to the method, where we are adding circular overlays to . Go ahead and add the following to the end of the method:

varlocations=places.map{$0.coordinate}

letpolyline=MKPolyline(coordinates:&locations,count:locations.count)

mapView?.add(polyline)

These 3 lines of code do the following:

  1. Extract the coordinates of each of the places contained in .
  2. Create a polyline from the places extracted in step 1.
  3. Add the polyline to the map view.

Here please take a special note of the way we pass in the parameter to the initializer for .

We need to provide an instead of . Since is an Objective C structure and not an subclass, regular instances cannot handle it. We cannot provide our coordinates as an array directly because Swift is unable to bridge this array to its Objective C type, as there is no Objective C type for an array of C structs. Without getting into low level language topics such as bridging and memory management, it’s necessary to know that an array you pass to a function as an must be declared with , not . You must also prefix the array’s name with an to indicate to Swift that you wish to provide that parameter as an type. Additionally, you need to provide the count of the array you pass in so that Objective C can determine how many objects have been provided.

Your function should look like this:

funcaddAnnotations(){

    mapView?.delegate=self

    mapView?.addAnnotations(places)

 

    letoverlays=places.map{MKCircle(center:$0.coordinate,radius:100)}

    mapView?.addOverlays(overlays)

    

    varlocations=places.map{$0.coordinate}

    letpolyline=MKPolyline(coordinates:&locations,count:locations.count)

    mapView?.add(polyline)

}

Now that we have provided the polyline overlay to MapKit, we need to tell MapKit how to render the overlay. Remember how we provided an when we wanted to render a circle? We need to provide a renderer for polylines as well, but it’s suprisingly easy.

Let’s navigate to in and get started. The first thing we need to do is modify this method so that it can check what kind of overlay is being rendered and respond appropriately. We can do this using Swift’s operator, which will allow us to check if one object is a subclass of another, like so:

ifanimalisDog{

 

}

 

else{

 

}

As you can see, Swift’s type checking syntax is pretty awesome, and it lets us easily check the type of an object. Let’s use this principle and apply it to our MapKit scenario:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

funcmapView(_mapView:MKMapView,rendererFor overlay:MKOverlay)->MKOverlayRenderer{

    ifoverlayisMKCircle{

        letrenderer=MKCircleRenderer(overlay:overlay)

        renderer.fillColor=UIColor.black.withAlphaComponent(0.5)

        renderer.strokeColor=UIColor.blue

        renderer.lineWidth=2

        returnrenderer

    

    }elseifoverlayisMKPolyline{

        letrenderer=MKPolylineRenderer(overlay:overlay)

        renderer.strokeColor=UIColor.orange

        renderer.lineWidth=3

        returnrenderer

    }

    

    returnMKOverlayRenderer()

}

Easy, right? We just check what kind of overlay we’re rendering and act accordingly. is self explanatory for those who have worked with renderer, as the setup process is identical. Build and run the app, and voila! You should see a blue polyline that runs between New York, LA, and San Francisco.

map-polyline

Drawing Polygons

Now that we’ve drawn a polyline, let’s move on and see how to draw a polygon. If you don’t remember from Math class, a polygon is a closed shape made up of multiple points, with straight lines connecting each of the points. MapKit also provides us with a class for rendering polygons. It’s called .

As you may have inferred already, it’s pretty easy to use. Let’s go back to and add our polygon. But before we do this, let’s clean up our code a little bit. Currently, our function is responsible for adding annotations and a polyline. This doesn’t hold true to its name, so let’s make a new method called and move our polyline code from to our new function:

funcaddPolyline(){

    varlocations=places.map{$0.coordinate}

    letpolyline=MKPolyline(coordinates:&locations,count:locations.count)

    

    mapView?.add(polyline)

}

Let’s also create an empty method called :

funcaddPolygon(){

    

}

Finally, modify the method to call all of our overlay methods. Your method should look like this:

overridefuncviewDidLoad(){

    requestLocationAccess()

    

    addAnnotations()

    addPolyline()

    addPolygon()

}

Okay, it is time to implement the method. To draw a polygon on map, you just need a few lines of code. Insert the following code in the method:

varlocations=places.map{$0.coordinate}

letpolygon=MKPolygon(coordinates:&locations,count:locations.count)

mapView?.add(polygon)

This is really similar to adding a polyline, and that’s intentional. Well-designed frameworks provide developers with consistency and predictability. MapKit’s mature API gives developers both of those things. Note that we still have the little oddity that we did when we worked with : we need to provide our as an . Just like before, you need to declare your array with and prefix its name with an when passing it to the function.

Great! We just need to provide MapKit with a renderer like we did for and . Head to in and add a third branch to the statement we were using before:

elseifoverlayisMKPolygon{

 

}

Now we can check if we’re rendering a polygon and respond appropriately. As we did before, we’re going to set up a renderer and return it so that MapKit knows how to display our polygon. Add the following code to the branch:

letrenderer=MKPolygonRenderer(polygon:overlay as!MKPolygon)

renderer.fillColor=UIColor.black.withAlphaComponent(0.5)

renderer.strokeColor=UIColor.blue

renderer.lineWidth=2

returnrenderer

Easy, right? We set up another renderer just like we did with our other shapes and return it. Your should look like this:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

funcmapView(_mapView:MKMapView,rendererFor overlay:MKOverlay)->MKOverlayRenderer{

    ifoverlayisMKCircle{

        letrenderer=MKCircleRenderer(overlay:overlay)

        renderer.fillColor=UIColor.black.withAlphaComponent(0.5)

        renderer.strokeColor=UIColor.blue

        renderer.lineWidth=2

        returnrenderer

    

    }elseifoverlayisMKPolyline{

        letrenderer=MKPolylineRenderer(overlay:overlay)

        renderer.strokeColor=UIColor.orange

        renderer.lineWidth=3

        returnrenderer

    

    }elseifoverlayisMKPolygon{

        letrenderer=MKPolygonRenderer(polygon:overlay as!MKPolygon)

        renderer.fillColor=UIColor.black.withAlphaComponent(0.5)

        renderer.strokeColor=UIColor.orange

        renderer.lineWidth=2

        returnrenderer

    }

    

    returnMKOverlayRenderer()

}

Now, build and run. Let’s take a look. You should see a polygon between the 3 cities shown on the map.

map-polygon

You should notice that the overlays we have provided scale proportionately, depending on the scale of the map. This makes adding overlays superior to adding a subview to because overlays scale and translate automatically, but regular views would not.

Adding Callouts

So far, we’ve learned how to display annotations, circles, polylines, and polygons. Now, let’s revisit annotations and make ours better. What if someone using our app doesn’t know which city is which? For example, what if someone does not know which of the 3 cities is New York?

We should provide a way for them to check. We can do this with callouts, which are little bubbles that appear when annotations are tapped. Currently, tapping an annotation in our app does nothing. But we can make it work by showing a callout bubble.

Go to in and update the branch of our code that returns an annotation view for our custom annotations. We need to tell MapKit that the annotation views we’re providing can show callouts. Unsurprisingly, this is easy. Before , add a line of code that reads , so that reads like this:

funcmapView(_mapView:MKMapView,viewFor annotation:MKAnnotation)->MKAnnotationView?{

    ifannotationisMKUserLocation{

        returnnil

    }else{

        letannotationView=mapView.dequeueReusableAnnotationView(withIdentifier:"annotationView")??MKAnnotationView()

        annotationView.image=UIImage(named:"place icon")

        annotationView.canShowCallout=true

        returnannotationView

    }

}

Easy, right? Let’s build and run and see what happens. Tap on an annotation view and observe the callout that appears.

map-callouts

Now, our users can easily check what city they’re looking at, just by tapping. Let’s expand this ability a little bit further by allowing our users to view more detail within a callout. First, we need to add buttons to our callout. This is easy to do. Modify :

funcmapView(_mapView:MKMapView,viewFor annotation:MKAnnotation)->MKAnnotationView?{

    ifannotationisMKUserLocation{

        returnnil

 

    }else{

        letannotationView=mapView.dequeueReusableAnnotationView(withIdentifier:"annotationView")??MKAnnotationView()

        annotationView.image=UIImage(named:"place icon")

        annotationView.rightCalloutAccessoryView=UIButton(type:.detailDisclosure)

        annotationView.canShowCallout=true

        returnannotationView

    }

}

Now our callout will display a detail disclosure button when it’s clicked. We can respond to this button being clicked with a function called .

Let’s implement this function in the :

funcmapView(_mapView:MKMapView,annotationView view:MKAnnotationView,calloutAccessoryControlTapped control:UIControl){

    guard letannotation=view.annotationas?Place,lettitle=annotation.titleelse{return}

    

    letalertController=UIAlertController(title:"Welcome to \(title)",message:"You've selected \(title)",preferredStyle:.alert)

    letcancelAction=UIAlertAction(title:"OK",style:.cancel,handler:nil)

    alertController.addAction(cancelAction)

    present(alertController,animated:true,completion:nil)

}

This method will be called whenever a user taps on a button in a callout. It will retrieve the name of the city that belongs to that callout and display it in the alert. Give it a try. Build and run, tap a city, and then select a callout. You should see a message in the console that prints the name of the city the user selected.

map-callout-response

Wrapping up

I hope you enjoyed this tutorial! Even more importantly, I hoped you gained some valuable knowledge that you can use in your own apps. If you have any questions or comments, feel free to comment them below. Good luck!

For reference, you can download the complete Xcode project on GitHub.

Sours: https://www.appcoda.com/mapkit-polyline-polygon/

Polyline mapkit

I walked around Warsaw, put on Polish. I got dressed up, they often confused me with a girl. Well, at work, all these panties, bras, stockings, belts. natural plastic stands like women.

SwiftUI Tutorial - MapKit, Route, and Directions

Her eyes glittered, her head was completely indifferent. She thought about nothing, no worries, no troubles, her brain was just resting, atelo was charged more and more with the energy of passion. She didnt even see anything wrong when the professor hugged her into the massage room, when he patted her elastic ass, so that there were traces of her. Palm.

Now discussing:

It blows so well here. Be careful not to blow out, or else you will get sick. Yes, everything will be fine.



1645 1646 1647 1648 1649