I'm using for a way to update an annotation programmatically. I'm playing with SwiftUI and UIViewRepresentable. The map is shown. It is also not a problem to display an annotation on the map.
What I need now is this: I'm having a location provider, which delivers CLLocation2D coordinates. I would like to display the changing position on a map, but can't figure out how.
The location update is provided via an ObservableObject. That works. If I display the updates in Text element, I can see them:
#ObservedObject var pushedPoseClient = PushedPosesClient()
...
Text(String(format: "%.10f %.10f", self.pushedPoseClient.position.latitude ?? 0, self.pushedPoseClient.position.longitude ?? 0))
The same mechanism doesn't work for a map. I thought I could see updateUIView calls with every position update, but there are no.
How can an ObservedObject, which changes its coordinates, be displayed on a map?
The key is to have a CLLocation2D as observed object. Then it works.
Related
I need to add Compass or rotation with Map. This is my code. I am using Custom marker. I know we can add compass with MKMapView. But I have added many features to the Map using Map class like custom View Markers, longPress pin drop etc. Therefore, moving to MKMapView would be like redoing everything from scratch again.
Map(coordinateRegion: $mapRegion , annotationItems: viewModel.locations) { location in
MapAnnotation(coordinate: location.coordinate) {
MarkerView(location: location)
}
}
Anybody can tell me how I can do compass rotation with Map.
Thanks
You may be able to set these properties on the underlying view via the Introspect framework. It does not handle Map() out of the box, so you would have to follow the section on implementing your own selector. As the project's Read Me states, there are some caveats:
Please note that this introspection method might break in future SwiftUI releases. Future implementations might not use the same hierarchy, or might not use UIKit elements that are being looked for. Though the library is unlikely to crash, the .introspect() method will not be called in those cases.
I have also found that you need to really be careful and heavily test which property you set (or update) when and where.
We are using the Map functionality with annotations.
Functionality:- We have 2000 records in the array but we need to filter 150 records according to the region changed in the Map in SwiftUI. But there is no scroll end event of the Map in SwiftUI.
We used the below code
Map(coordinateRegion: self.$viewModel.region, interactionModes: [.all], annotationItems: self.viewModel.mapLocations), annotationContent: { pin in
}
We got the latest updated region in .onChange(of: viewModel.region) }. But we did not get the map scroll end event. We put the code in onChange(of) but it's lagging while scrolling. So, It's not worked for us.
Also. We tried Drag-Gesture but won't worked.
.gesture(DragGesture()
.onEnded { value in
//Did not getting this event while map scroll end
})
SwiftUI does not usually work as expected when trying to override gestures for built-in views especially with Map
Combine with .debounce is usually a better solution when it comes to filtering based on rapid changing #Published like a region
I have just build an swift app that takes data+coords from dynamoDB and puts it onto the ios mapkit. There are two sets of coords: one for current user location and one from dynamoDB. I want these coords to be able to update inside the map, but do not want the actual mapView to zoom and move at all (only the user can zoom and move).
I have achieved everything above except the last part. Currently whenever the annotations are added and mapView.showAnnotations is called, the mapView zooms and moves to enclose the annotations. How do I disable this?
To show mapView annotations without updating mapView zoom and constraints, use addAnnotations() rather than showAnnotations.
I am guessing that you used code from online (which we all do, no worries) and that your code looked something like this. If I am right, then you likely have a line somewhere like this:
[map setRegion:scaledRegion animated:YES];
That line is the issue. You need to use some sort of boolean to make it so that it only happens once. So you could set the boolean has_mapped = false until you have called your update method once, at which point it = true. Then change your line to say something like,
if (has_mapped)
[map setRegion:scaledRegion animated:YES];
I'm designing an app using Swift for a food truck. I want to use MapKit to show a pin on the live location of the truck so one can look at the app to see it moving in realtime. I was able to get the server-side element set up using PHP/MySQL. Currently, the app makes a HTTP request every 3 seconds.
How should I go about animating the moving pin (or other image)? I tried a few methods already (if you have others, please suggest!):
I removed the pin and quickly added a new one in my HTTP function. While this works, I would prefer a smooth animation, not a flashing, jerky pin.
I subclassed MKMapViewDelgate like with a didAddAnnotationViews delegate that animates the pin's frame using UIView.animateWithDuration as suggested here. Animation only occurred when the map was initially loaded. Also, I have no idea how this would work with coordinates, since it involves frames.
I subclassed MKAnnotation with a modifiable var coordinate. In my HTTP function, I changed the coordinate. EDIT: This now works since I properly refreshed the mapView (thanks #Paulw11). However, I still have two main issues:
There's no linear animation, which I desire to better simulate real-time movement. How would I go about animating the pin's coordinates? Should I use UIView, like in method 2, a fast NSTimer, or something else?
Due to using the setCenterCoordinate function to forcibly refresh the map, the map cancels any current touches. How do I detect if there's any touches on the MapView so I can prevent the forced update?
I'm having in my app a GMSPanoramaView witch contains some street view images.
I want to change those images to several locations with different 'heading' - directions.
I can't see a way to update the view with the new location, and the new heading at the same time.
The only way I can see is updating the location (by moveNearCoordinate func)
and only after the camera's heading (by updateCamera: func).
But this way cause a 'jump' in the seeing image -
the view presenting the new location, and than jumping to the wanted heading.
(the same will happens if i will update the camera first, and than the location).
I want the view to present the new location with specific direction Immediately.
I will be happy for some solution.
thanx.
You should make your heading changes in this method given to you by the GMSPanoramaViewDelegate
- (void)panoramaView:(GMSPanoramaView *)view
didMoveToPanorama:(GMSPanorama *)panorama
nearCoordinate:(CLLocationCoordinate2D)coordinate
In this method, you should only call self.view = self.panoramaView; after you've changed the heading by updating the camera. This is how I fixed a similar issue I was facing with the setting the heading of the panoramaView.
func panoramaViewDidFinishRendering(_ panoramaView: GMSPanoramaView) {
if (flag_init){
flag_init = NO
panoramaView.camera = GMSPanoramaCamera(heading: 180, pitch: 1, zoom: 1)
panoramaView.alpha = 1
}
}
i can't find how can do it but can minimize the time , of course you can modify the code to make sure the alpha value become 1 for second finish rendering