Display map or satellite imagery from your app's interface, call out points of interest, and determine placemark information for map coordinates using MapKit.

Posts under MapKit tag

144 Posts
Sort by:

Post

Replies

Boosts

Views

Activity

Draw Indoor Navigation path using ARKit iOS
I have indoor map and I want to draw path between two route location ex. from A to B I want to draw ARKit based Arrow path in ios Application. Currently I am using ARAnchor to achieve this but challenges is if A to B is 10 meter and I am adding Nodes on each one meter so instead of 10 different nodes i am getting single Arrow nodes showing all 10 in it. I am using below code. // Below Code from where I am calling addArpath function if let lat1 = mCurrentPosition?.latitude, let long1 = mCurrentPosition?.longitude { let latEnd = steplocation.latitude let longEnd = steplocation.longitude // if let lastLat = arrpath.last?.latitude,let lastLong = arrpath.last?.longitude,let lastAltitude = arrpath.last?.altitude{ let userLocation = CLLocation(latitude: lat1, longitude: long1) let endLocation = CLLocation(coordinate: CLLocationCoordinate2DMake(CLLocationDegrees(latEnd), CLLocationDegrees(longEnd)), altitude: CLLocationDistance(steplocation.altitude), horizontalAccuracy: CLLocationAccuracy(5), verticalAccuracy: CLLocationAccuracy(0), course: CLLocationDirection(-1), speed: CLLocationSpeed(5), timestamp: Date()) let heading = getHeadingForDirectionFromCoordinate(from: userLocation, to: endLocation) let lon1 = degreesToRadians(long1) //DegreesToRadians(long1) let lon2 = degreesToRadians(longEnd); //DegreesToRadians(longEnd); let lat2 = degreesToRadians(latEnd); let dLon = lon2 - lon1 let y = sin(dLon) * cos(lat2); yVal = yVal + y // let distanceToendpoint = calculateDistance(lat: endLocation.coordinate.latitude, long: endLocation.coordinate.longitude) let distvalue = Int(distance) + Int(pathlength) distance += CGFloat(distvalue) for i in stride(from: 0, to: distance, by:1) { print("current loop iteration is:" ,i) let headingValue = heading - self.heading zValue = zValue + headingValue distanceVal = CGFloat(i) + distanceVal zGlobal = zValue // Calling addARPathtoLocation addARPathtoLocation(stepLocation:endLocation,zvalue: zValue, yvalue: yVal, distance:Float(i), direction: manuoverType) } // } } // MARK: - ARSessionDelegate func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) { guard !(anchor is ARPlaneAnchor) else { return } let sphereNode = generateArrowNodes(anchor: anchor) DispatchQueue.main.async { node.addChildNode(sphereNode) } } //create ARAnchor to add to nodes func generateArrowNodes(anchor: ARAnchor) -> SCNNode { let imageMaterial = SCNMaterial() imageMaterial.isDoubleSided = true imageMaterial.diffuse.contents = UIImage(named: "blueArrow") let plane = SCNPlane(width:0.5, height:0.5) plane.materials = [imageMaterial] plane.firstMaterial?.isDoubleSided = true let blueNode = SCNNode(geometry: plane) blueNode.name = "blueNode" blueNode.position = SCNVector3(x:Float(zGlobal), y:0, z:Float(distanceVal)) blueNode.eulerAngles.x = -.pi / 2 blueNode.eulerAngles.y -= Float(CGFloat(CGFloat.pi/4*6)) return blueNode } func addARPathtoLocation(stepLocation: CLLocation, zvalue: CGFloat, yvalue: CGFloat, distance:Float, direction:VMEManeuverType) { // give you the depth of anything ARKit has detected guard let query = sceneView.raycastQuery(from: sceneView.center , allowing: .estimatedPlane, alignment: .any) else { return } let results = sceneView.session.raycast(query) guard let hitResult = results.first else { print("No surface found") return } // Add ARAnchor to Scene let anchor = ARAnchor(transform: hitResult.worldTransform) sceneView.session.add(anchor: anchor) } func radiansToDegrees(_ radians: Double) -> Double { return (radians) * (180.0 / Double.pi) } func degreesToRadians(_ degrees: Double) -> Double { return (degrees) * (Double.pi / 180.0) } func getHeadingForDirectionFromCoordinate(from: CLLocation, to: CLLocation) -> Double { let fLat = degreesToRadians(from.coordinate.latitude) let fLng = degreesToRadians(from.coordinate.longitude) let tLat = degreesToRadians(to.coordinate.latitude) let tLng = degreesToRadians(to.coordinate.longitude) let deltaL = tLng - fLng let x = sin(deltaL) * cos(tLng) //cos(tLat) * sin(deltaL) let y = cos(fLat) * sin(tLat) - sin(fLat) * cos(tLat) * cos(deltaL) let bearing = atan2(x,y) let bearingInDegrees = bearing.toDegrees print("Bearing Degrees :",bearingInDegrees) // sanity check // let degree = radiansToDegrees(atan2(sin(tLng-fLng)*cos(tLat), cos(fLat)*sin(tLat)-sin(fLat)*cos(tLat)*cos(tLng-fLng))) if bearingInDegrees >= 0 { return bearingInDegrees } else { return bearingInDegrees + 360 } }
0
0
81
2d
MapKit mapItemDetailAccessory Custom View
Hi all, It wasn't extensively covered in the "Unlock the power of places with MapKit" at WWDC, but is it possible to add your own views to the mapItemDetailAccessory? The default view is great, but I would like to add a button for opening a new window showing another view. The documentation is rather limited at the moment so I thought I would ask here. Thanks in advance.
0
0
87
1w
mapItemDetailSheet Not Displaying Information
I'm on MacOS 15 Beta and Xcode 16 Beta. Running iOS 18 Beta on a 15 Pro Max. I'm leveraging the .mapItemDetailSheet(item: input) option to pull up a sheet that displays the Place Card for a selection made from a List of places. This is working great on my iPhone 15 Pro Max and my iPad Pro 13. I also have the Mac Catalyst option added under: Project \ General \ Supported Destinations If I launch the app from Xcode via the play button, the app functions fine on my MacBook Pro and I get logs in Xcode, etc. However, if stop the session in Xcode and attempt to run the same app on its own on my MacBook Pro, the mapItemDetailSheet does not populate with any information. Anyone have ideas on where the disconnect could be? Why would the sheet populate with data when ran from Xcode but not when ran on its own? Again, it runs fine on the iPhone and iPad. Any ideas would be helpful and appreciated.
0
0
105
1w
Apple Maps Pins in Custom Map
I have been developing an app that includes some pinned locations. These are displayed on a map, and currently have the standard pins and SF Symbol pins. A few of the locations have a special symbol on Apple Maps, but the same symbol is not avalable in SF Symbols. I was wondering if it is possible to use the pins, other than the standard red, from Apple Maps.
0
0
194
2w
mapItemDetailSheet Behavior Question
I'm on MacOS 15 Beta and Xcode 16 Beta. Running iOS 18 Beta on a 15 Pro Max. I'm leveraging the .mapItemDetailSheet(item: input) option to pull up a sheet that displays the Place Card for a selection made from a List of places. What I'm seeing is that the first tap fails to pull up the sheet and it auto closes pretty much immediately. But then loads correctly on the second tap. Other times it will not auto close, but simply fail to load the item details in the sheet. Again, though, if I close the sheet and tap a second time it loads without issue. I'm posting to get some feedback as to whether this is most likely caused by bad code (I'm very new to this) or if it is known behavior and due to the Beta software. Any insight from the community would be helpful. Thanks in advance.
1
0
153
2w
Places with MapKit Questions
Hello, I'm very interested in utilizing Place ID with MapKit. Reference: https://developer.apple.com/videos/play/wwdc2024/10097/ I do have some questions I've been unable to find in documentation or within the demo. Apologies in advance if they have been added since. Are place photos included with the call? It appeared so in the demo just want to make sure as I was unable to confirm in the documentation.) Are star ratings included with the Place ID? Reason: Looking for ways to display top/popular POI around a location. How do rate limits work? Can places be cached? (We're looking to keep saved/bookmarked POI cached to avoid pinging MapKit each time the app is used) How often is place data refreshed? For example if a new restaurant opens in town when will it be available to display. Can search provide place results by name (in and out burger) and by type (burgers in LA)? Would we have to pick one way or the other for search to work in this case? Thanks in advance.
0
0
123
2w
SwiftUI+MapKit cannot display the globe view on iPhone.
I hope to use SwiftUI and MapKit to achieve the effect of a globe view when zooming out on the map. The code works in Xcode’s simulator and Simulator, but when running on my iPhone, it only zooms out to a flat world map. I haven’t found anyone else encountering the same issue, so I’d like to ask where the problem might be. Below is the simple code: import SwiftUI import MapKit struct GlobalTest: View { var body: some View { Map(position: .constant(.automatic), interactionModes: [.all, .pan, .pitch, .rotate, .zoom]) { } .mapStyle(.hybrid(elevation: .realistic, pointsOfInterest: .including([.park]), showsTraffic: false)) } } #Preview { GlobalTest() } I have also tried setting the camera properties, but it still doesn’t work. My phone is an iPhone 15 Pro Max, running iOS 17.5.1, and I am in mainland China. The Xcode version is the latest. If anyone understands the reason, please let me know. This is very important to me, and I would be very grateful!
1
0
188
2w
Multi Polygons MapKit
Is MultiPolygon overlay support going to be integrated with SwiftUI? I have made a post on here previously without a reply :( Any suggestions on how to display multi-polygons within MapKit for SwiftUI(https://developer.apple.com/documentation/mapkit/mappolygon)? At the moment it is not supported and only supported by MapKit for UIKit(https://developer.apple.com/documentation/mapkit/mkmultipolygon).
2
0
193
1w
Importing json file and displaying POI's in Mapkit using Xcode 15 and swiftUI
Description: I am working on an iOS 17 app using Xcode 15 and SwiftUI. The app involves displaying points of interest (POIs) on a MapView based on user proximity and other factors such as hours of operation. The data for the POIs is stored in a JSON file, which I am trying to import and parse in the project. However, I have encountered several issues: Deprecation Errors: When attempting to use MapAnnotation, I receive deprecation warnings and errors. It seems that MapAnnotation has been deprecated in iOS 17, and I need to use the new Annotation API along with MapContentBuilder. RandomAccessCollection Conformance: Errors related to RandomAccessCollection conformance when using Map with SwiftUI. JSON Import and Parsing: I used Bundle.main.url(forResource: "locations", withExtension: "json") to load the JSON file but faced issues with correctly parsing and mapping the JSON data to my model objects. What I Need: Guidance on how to correctly use the new Annotation API and MapContentBuilder for displaying POIs on a MapView in iOS 17. Best practices for importing and parsing JSON files in SwiftUI, especially for dynamically updating the MapView based on user proximity and other criteria like hours of operation. Any relevant code snippets or examples would be greatly appreciated. Example of What We Tried Model: swift Copy code struct POI: Codable, Identifiable { let id: Int let name: String let latitude: Double let longitude: Double let hours: [String: String] } Loading JSON: swift Copy code func loadPOIs() -> [POI] { guard let url = Bundle.main.url(forResource: "locations", withExtension: "json"), let data = try? Data(contentsOf: url) else { return [] } let decoder = JSONDecoder() return (try? decoder.decode([POI].self, from: data)) ?? [] } Map View: swift Copy code import SwiftUI import MapKit struct ContentView: View { @State private var pois: [POI] = loadPOIs() @State private var region = MKCoordinateRegion( center: CLLocationCoordinate2D(latitude: 40.7128, longitude: -74.0060), span: MKCoordinateSpan(latitudeDelta: 0.05, longitudeDelta: 0.05) ) var body: some View { Map(coordinateRegion: $region, annotationItems: pois) { poi in MapAnnotation(coordinate: CLLocationCoordinate2D(latitude: poi.latitude, longitude: poi.longitude)) { VStack { Text(poi.name) Circle().fill(Color.red).frame(width: 10, height: 10) } } } } } Issues Encountered: MapAnnotation is deprecated. Errors related to RandomAccessCollection conformance. Any advice or solutions for these issues would be greatly appreciated. Thank you!
1
0
243
3w
SwiftUI map lags when it's centered in the user's location and state changes
Please note that for this app to be able show you your location on the map you need to enable it to ask for permission to track the user's location, in the project's targets' info: Here's also a video that illustrates the lag: https://youtube.com/shorts/DSl-umGxs20?feature=share. That being said, if you run this SwiftUI app and allow it to track your location, tap the MapUserLocationButton and press the buttons at the bottom, you'll see that the map lags: import SwiftUI import MapKit import CoreLocation struct ContentView: View { let currentLocationManager = CurrentUserLocationManager() let mapLocationsManager = MapLocationsManager() @State private var mapCameraPosition: MapCameraPosition = .automatic var body: some View { Map( position: $mapCameraPosition ) .safeAreaInset(edge: .bottom) { VStack { if mapLocationsManager.shouldAllowSearches { Button("First button") { mapLocationsManager.shouldAllowSearches = false } } Button("Second button") { mapLocationsManager.shouldAllowSearches = true } } .frame(maxWidth: .infinity) .padding() } .mapControls { MapUserLocationButton() } } } @Observable class MapLocationsManager { var shouldAllowSearches = false } // MARK: - Location related code - class CurrentUserLocationManager: NSObject { var locationManager: CLLocationManager? override init() { super.init() startIfNecessary() } func startIfNecessary() { if locationManager == nil { locationManager = .init() locationManager?.delegate = self } else { print(">> \(Self.self).\(#function): method called redundantly: locationManager had already been initialized") } } }; extension CurrentUserLocationManager: CLLocationManagerDelegate { func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) { checkLocationAuthorization() } }; extension CurrentUserLocationManager { private func checkLocationAuthorization() { guard let locationManager else { return } switch locationManager.authorizationStatus { case .notDetermined: locationManager.requestWhenInUseAuthorization() case .restricted: print("Your location is restricted") case .denied: print("Go into setting to change it") case .authorizedAlways, .authorizedWhenInUse, .authorized: // locationManager.startUpdatingLocation() break @unknown default: break } } } I've also tried in a UIKit app (by just embedding ContentView in a view controller), with the same results: import UIKit import MapKit import SwiftUI import CoreLocation class ViewController: UIViewController { let currentLocationManager = CurrentUserLocationManager() override func viewDidLoad() { super.viewDidLoad() currentLocationManager.startIfNecessary() let hostingController = UIHostingController( rootView: MapView() ) addChild(hostingController) hostingController.view.frame = view.bounds hostingController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight] view.addSubview(hostingController.view) hostingController.didMove(toParent: self) } } extension ViewController { struct MapView: View { let mapLocationsManager = MapLocationsManager() @State private var mapCameraPosition: MapCameraPosition = .automatic var body: some View { Map( position: $mapCameraPosition ) .safeAreaInset(edge: .bottom) { VStack { if mapLocationsManager.shouldAllowSearches { Button("First button") { mapLocationsManager.shouldAllowSearches = false } } Button("Second button") { mapLocationsManager.shouldAllowSearches = true } } .frame(maxWidth: .infinity) .padding() } .mapControls { MapUserLocationButton() } } } } extension ViewController { @Observable class MapLocationsManager { var shouldAllowSearches = false } } class CurrentUserLocationManager: NSObject { var locationManager: CLLocationManager? func startIfNecessary() { if locationManager == nil { locationManager = .init() locationManager?.delegate = self } else { print(">> \(Self.self).\(#function): method called redundantly: locationManager had already been initialized") } } }; extension CurrentUserLocationManager: CLLocationManagerDelegate { func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) { checkLocationAuthorization() } }; extension CurrentUserLocationManager { private func checkLocationAuthorization() { guard let locationManager else { return } switch locationManager.authorizationStatus { case .notDetermined: locationManager.requestWhenInUseAuthorization() case .restricted: print("Your location is restricted") case .denied: print("Go into setting to change it") case .authorizedAlways, .authorizedWhenInUse, .authorized: // locationManager.startUpdatingLocation() break @unknown default: break } } } If you don't center the map in the user's location, you might see an occasiona lag, but it seems to me that this only happens once. How do I avoid these lags altogether? Xcode 15.4
1
0
202
3w
How do I make a map with selectable `MKMapItem`s in iOS 17?
I want to display an Apple map in my UIKit app, but if I try to do so with UIKit I get concurrency-related warnings (Xcode 15.4 with strict concurrency warnings enabled) that I couldn't find a proper solution to. So I opted for SwiftUI, and for the iOS 17 approach, specifically, (WWDC23). The following code displays a map with a marker. If you look at the Map initializer, you can see that a map camera position and a map selection are specified. If you run the app, however, you can't actually select the marker, unless you uncomment .tag(mapItem). import SwiftUI import MapKit struct MapView: View { @State private var mapCameraPosition: MapCameraPosition = .automatic @State private var mapSelection: MKMapItem? let mapItem = MKMapItem( placemark: .init( coordinate: .init( latitude: 37, longitude: -122 ) ) ) var body: some View { Map( position: $mapCameraPosition, selection: $mapSelection ) { Marker(item: mapItem) // .tag(mapItem) } .onChange(of: mapSelection) { _, newSelection in print("onChange") // never prints if let _ = newSelection { print("selected") // never prints } } } } If you give another tag, like 1, the code once again doesn't work. Is that really the way to go (that is, is my code with fine once you uncomment .tag(mapItem))? If not, how do I make a map with selectable MKMapItems in iOS 17? iOS 17.5, iPhone 15 Pro simulator, Xcode 15.4, macOS 14.5, MacBook Air M1 8GB.
1
0
278
4w
MKLocalSearch missing Music Venues from response
I have created an MKLocalSearch request as follows: let reqVenue = MKLocalSearch.Request() reqVenue.naturalLanguageQuery = "Music Venue" reqVenue.resultTypes = .pointOfInterest reqVenue.region = .init(center: mockCoord, latitudinalMeters: 150, longitudinalMeters: 150) I have made sure mockCoord is the exact location coordinate of the example music venue I want to get back in the response. I have noticed that all Music Venues I can find on Apple Maps do not come back as results in MKLocalSearch. I would love an explanation as to why and what I can do to make them appear in MKLocalSearch results please! best, nick
1
0
241
3w
Flickering after removing MapKit MapPolygons/Polylines
I'm using MapKit for SwiftUI and having an issue when conditionally rendering MapPolygons or MapPolylines. Removing these overlays after a previous render causes them to flicker sporadically in their previous location when a user zooms or moves the camera. The relevant code is as follows: Map(position: $cameraPosition, scope: mapScope) { MapPolygon(coordinates: selectedTileVertices) .stroke( Color(red: 1.0, green: 1.0, blue: 1.0, opacity: isTileSelected ? 1.0 : 0.0), style: StrokeStyle(lineWidth: 5, lineJoin: .round)) .foregroundStyle(selectedTile.color.opacity(0.0)) } A polygon is rendered around a coordinate that a user selects. Upon selecting a new coordinate, a new polygon should render and the old be completely removed from the map. In practice, the new polygon is rendered and the old initially removed, but upon zooming the old polygon flickers in and out of appearance. At some zoom levels the old polygon is completely visible again. The crux of the problem sees to be that I am using .mapStyle(.imagery(elevation: .realistic)). Upon switching to .hybrid all flickering behavior is gone. The flickering becomes worse when doing a lot of zooming/camera movement while the old polygon is rendered and then swapping to a new polygon, and is largely nonexistent if swapping to a new polygon at the same zoom level. I imagine this has something to do with the extra rendering optimizations for satellite imagery. Any help resolving this issue would be appreciated.
0
0
246
May ’24
API Key for MapKit not working for Delphi/TMS
I have generated a key for MapKit and it gave me a private key (p8), a Key ID and a MapKit JS key. I am trying to use MapKit in Delphi TMS FNC Maps but it does not seem to render the maps. The same code works with Google Map Key, but not Apple MapKit. I was told to use the MapKit JS key in TMS by the vendor, but neither the Key ID or the MapKit JS key worked. Any help on this is greatly appreciated. Thank you
1
0
285
May ’24
How to show user heading (facing direction) in MapKit SwiftUI
I want to show what direction a user is facing (the blue cone that you get in Apple Maps), but I can't find a way to show it with SwiftUI. The closest I've found is this init signature for UserAnnotation: https://developer.apple.com/documentation/mapkit/userannotation/4235435-init But it only gives heading data once you press the map orientation button, to always show the forward direction. I want to show the cone in the normal map, without reorienting it.
1
2
249
May ’24
Mapkit SwiftUI iOS17
I am trying to load and view several locations onto a map from a JSOPN file in my SwiftUI project, but I continually encounter the error "no exact matches in call to initializer" in my ContentView.swift file. What I Am Trying to Do: I am working on a SwiftUI project where I need to display several locations on a map. These locations are stored in a JSON file, which I have successfully loaded into Swift. My goal is to display these locations as annotations on a Map view. JSON File Contents: coordinates: latitude and longitude name: name of the location uuid: unique identifier for each location Code and Screenshots: Here are the relevant parts of my code and the error I keep encountering: import SwiftUI import MapKit struct ContentView: View { @State private var mapPosition = MapCameraPosition.region( MKCoordinateRegion( center: CLLocationCoordinate2D(latitude: 37.7749, longitude: -122.4194), span: MKCoordinateSpan(latitudeDelta: 0.05, longitudeDelta: 0.05) ) ) @State private var features: [Feature] = [] var body: some View { NavigationView { Map(position: $mapPosition, interactionModes: .all, showsUserLocation: true) { ForEach(features) { feature in Marker(coordinate: feature.coordinate) { FeatureAnnotation(feature: feature) } } } .onAppear { POILoader.loadPOIs { result in switch result { case .success(let features): self.features = features case .failure(let error): print("Error loading POIs: \(error.localizedDescription)") } } } .navigationBarTitle("POI Map", displayMode: .inline) } } } struct FeatureAnnotation: View { let feature: Feature var body: some View { VStack { Circle() .strokeBorder(Color.red, lineWidth: 2) .background(Circle().foregroundColor(.red)) .frame(width: 20, height: 20) Text(feature.name) } } } I have not had any luck searching for solutions to my problems using the error messages that keep arising. Does anyone have any advice for how to move forward?
2
0
327
May ’24
SwiftUI and MapKit: Map camera position not updating when refreshing location
Map(initialPosition: .camera(mapCamera)) { Marker("Here", coordinate: location) } .frame(height: 300) .clipShape(RoundedRectangle(cornerSize: CGSize(width: 10, height: 10))) .onMapCameraChange(frequency: .continuous) { cameraContext in locationManager.location = cameraContext.camera.centerCoordinate } .onReceive(locationManager.$location, perform: { location in if let location { mapCamera.centerCoordinate = location } }) class LocationDataManager: NSObject, CLLocationManagerDelegate, ObservableObject { enum LoadingState { case loading case notLoading case finished } static let shared = LocationDataManager() private let locationManager = CLLocationManager() @Published var location: CLLocationCoordinate2D? = nil @Published var loading: LoadingState = .notLoading override init() { super.init() locationManager.delegate = self } func resetLocation() { loading = .notLoading location = nil } func getLocation() { locationManager.requestLocation() loading = .loading } func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { location = locations.first?.coordinate if location != nil { loading = .finished } } func locationManager(_ manager: CLLocationManager, didFailWithError error: any Error) { print("Failed to retrieve location: \(error.localizedDescription)") loading = .notLoading } } So the when the LocationButton is selected, the location is found and the marker is set correctly. You can also move the camera around to adjust the marker position, which works correctly. However, if you press the LocationButton again, it updates the marker position but it won't move the MapCamera to the new location. I can see the marker move. mapCamera.centerCoordinate = location should be doing it, but it's not. Anyone know how to fix this?
1
0
291
May ’24