Comments (4)
Sure - there are currently two ways of adding overlays to this Map implementation. You can either use MKPolyline (i.e. the more UIKit way of doing UI) or specify your own Identifiable structs and then create custom MapOverlays from that (i.e. the SwiftUI way of doing things). Which one would you like more help on?
For the SwiftUI approach, I just created a code example for circles that could be transformed into using MapPolyline instead of MapCircle in the closure that is given as a parameter of the Map initializer. (See #29 (comment))
For the UIKit approach, you would have something like this:
struct MyMapView: View {
@State private var overlays = [MKOverlay]()
@State private var region = MKCoordinateRegion()
var body: some View {
Map(
coordinateRegion: $region,
overlays: overlays
) { overlay in
// Create a MKOverlayRenderer here, for example something like this:
let renderer = MKPolylineRenderer(overlay: overlay)
renderer.lineWidth = 4
renderer.strokeColor = .black
return renderer
}
}
}
from map.
You mentioned adapting the #29 MapCircle to a MapPolyline but I could use a little help with that.
I have a set of locations from a @FetchRquest and want to make a polyline overlay from them. They are coredata objects from the fetch and I'm not sure where I turn them into array for the MapPolyline [CLLocationCoordinate2D]?
@FetchRequest(
sortDescriptors: [NSSortDescriptor(keyPath: \RoutePoint.timestamp, ascending: true)],
animation: .default)
private var route: FetchedResults<RoutePoint>
// I have something like this in the Map creation:
overlayItems: route,
overlayContent: { routePoint in
MapPolyline(coordinates: [CLLocationCoordinate2D(latitude: routePoint.latitude, longitude: routePoint.longitude)],
level: .aboveRoads,
strokeColor: .systemIndigo,
lineWidth: 5)
}
If I provide [CLLocationCoordinate2d] in overlayItems it complains it is not Identifiable (of course), so I'm not sure how these two parameters work together. I think an example would be helpful.
Your package looks quite helpful, but I haven't got it past showing the ocean at 0.0,0.0 yet either :^).
from map.
Could you make RoutePoint Identifiable? Maybe by using the timestamp or some unique identifier as id
property? Since RoutePoint further needs to conform to NSObject, you might just want to use ObjectIdentifier
as in the following example. It essentially uses the memory address of that object as its id, so as long as CoreData does not create new objects each time the request is fired but simply adapts the objects itself, this should work flawlessly.
extension RoutePoint: Identifiable {
public var id: ObjectIdentifier {
ObjectIdentifier(self)
}
}
And regarding the issue with showing the ocean at (0,0) - could it be that you are using .constant(.init())
as the region/mapRect parameter in the initializer of the Map? If you do this, then you will always force the map to use that region, which leads it to not move at all. What you would want to do instead is have a @State
wrapped property for either mapRect or region. If you don't modify it, it will simply be the user-defined value (and start at the value that you set it to initially), but you can then simply set that property and the map will move to that region/mapRect.
Edit: I think I misunderstood your point about the RoutePoint thing: You want to create one MapPolyline from all RoutePoints combined, right? Above is the solution for creating one MapPolyline per RoutePoint. Okay, in the case of one MapPolyline for all RoutePoints, it would probably make most sense to use something similar to what I did in this comment, where you would have some struct (let's call it OverlayItem
here) and you would create a new array of OverlayItem
with onChange(of:_:)
whenever the CoreData result changes, i.e.
struct OverlayItem: Identifiable {
let id = UUID()
let coordinates: [CLLocationCoordinate2D]
}
struct MyView: View {
@State private var region: MKCoordinateRegion = ... // or use `mapRect: MKMapRect ` instead
@State private var overlayItems = [OverlayItem]()
@FetchRequest(
sortDescriptors: [NSSortDescriptor(keyPath: \RoutePoint.timestamp, ascending: true)],
animation: .default)
private var route: FetchedResults<RoutePoint>
var body: some View {
Map(
coordinateRegion: $region, // or mapRect: $mapRect
overlayItems: overlayItems,
overlayContent: {
}
)
.onChange(of: route) { route in // not sure, if FetchedResults<RoutePoint> conforms to Equatable - if not, you might want to extend it accordingly
self.overlayItems = [
OverlayItem(
coordinates: route.map { point in
CLLocationCoordinate2D(latitude: point.latitude, longitude: point.longitude)
}
)
]
}
}
}
from map.
You are correct, I am trying to show a MapPolyline for a list of locations in CoreData. I think this may be a common use case. The challenge is that you are trying to support multiple overlays not just one polyline.
FetchedResults does not conform to Equatable but I don't want to do a complete comparison on it since Swifui responds to changes from an @FetchRequest (that's its reason for existing.) Now I'm trying to prepare the overlayItems in the view
and it seems to work, but I have to scroll the map to my current location (see below.)
My problem with the Ocean seems to be order of when my locationManager is getting set up. I changed it to have a default at Buckingham palace ;^). The thing I'm not seeing is the map following the location as I expected with the userTrackingMode I set.
I will be adding Annotations as well in the future, so I like your general solution to all of this.
The code I'm currently trying:
@State var region = MKCoordinateRegion(center: LocationPublisher.shared.lastLocation?.coordinate ??
CLLocationCoordinate2D(latitude: 51.5, longitude: -0.12),
latitudinalMeters: 1000,
longitudinalMeters: 1000)
@State private var userTrackingMode = UserTrackingMode.follow
var body: some View {
let overlayItems = [
OverlayItem(
coordinates: route.map { point in
CLLocationCoordinate2D(latitude: point.latitude, longitude: point.longitude)
}
)
]
Map(
coordinateRegion: $region,
type: .standard,
pointOfInterestFilter: .excludingAll,
informationVisibility: .default.union(.userLocation),
interactionModes: .all,
userTrackingMode: $userTrackingMode,
overlayItems: overlayItems,
overlayContent: { overlayItem in
MapPolyline(coordinates: overlayItem.coordinates,
level: .aboveRoads,
strokeColor: .systemIndigo,
lineWidth: 5)
}
)
from map.
Related Issues (20)
- Map Annotation selection HOT 1
- ViewMapAnnotation does not allow text HOT 2
- ViewMapAnnotation not updating location HOT 1
- Using current zoom factor in Annotations HOT 1
- ViewMapAnnotation doesn't support clustering HOT 4
- Package not recognised HOT 18
- impossible to have my liste of annotations HOT 1
- Issue with userTrackingMode HOT 8
- User location not showed HOT 6
- Map+Coordinator.swift:256 Modifying state during view update, this will cause undefined behavior.
- onTapGesture not working HOT 23
- watchOS support for overlays? HOT 2
- assertionFailure("Somehow a cluster contains an unknown annotation item.") HOT 8
- Fails to compile for macOS (Apple Silicon) HOT 2
- If an annotation is clustered and then this annotation is removed from the array of annotationItems, it throws error assertionFailure("Somehow a cluster contains an unknown annotation item." HOT 1
- Append a Text after an Image as ViewMapAnnotation not showed HOT 1
- Annotations aren't immobile and move with zoom HOT 4
- Running HOT 1
- can't use Map on VisionOS. error about userTrackingMode HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from map.