Maps & Location

RSS for tag

Learn how to integrate MapKit and Core Location to unlock the power of location-based features in your app.

Maps & Location Documentation

Post

Replies

Boosts

Views

Activity

App Clips Advanced Experiences not showing up in Apple Maps and Siri Suggestions
Hello everyone, I’m experiencing an issue with App Clips Advanced Experiences and Apple Maps/Siri Suggestions. We have already contacted Apple Support before, but they are investigating the cause of this issue and it has not been resolved til date. The App Clip is bundled with the main app and has been already available on the App Store for several months. The business running the app has several physical shops and wants to offer the App Clip to show up in Apple Maps and Siri Suggestions at each location. The App Clip is correctly exposed in the AASA file, and it's also validated correctly by the AASA APIs available at https://app-site-association.cdn-apple.com/a/v1. { "applinks": { "apps": [], "details": [ { "appID": "TEAMID.bundleid", "paths": [] } ] }, "appclips": { "apps": [ "TEAMID.bundleid.Clip" ] } } (with TEAMID and bundleid being the team and bundle identifiers of the app) The App Clip is displayed correctly when loading the website and when scanning a QR code or App Clip code, but doesn't appear in the Maps app or in Siri suggestions. We have set up the App Clip Advanced Experiences on the App Store Connect page of the app, and each URL has been linked to a physical shop. All URLs are in the "Received" state, so they should appear correctly on Maps. Unfortunately, I don't see any "Order" button in Apple Maps at any location card. We tried with both iOS 17 and 16. According to feedbacks from people in the shops, they don't see the app suggested in the Siri Suggestions. I have just submitted a Custom Action Link on Apple Business Connect for one of the shops, but without success: the App Clip doesn't appear. Any idea why is this happening?
6
1
508
Sep ’24
What is the reason for the CLLocationmanager.locationServicesEnabled() "invoked on main thread" warning?
I am looking into a piece of old code where the mentioned method is called. + (bool)isLocationServicesEnabled { return [CLLocationManager locationServicesEnabled]; } I'm getting the classic "This method can cause UI unresponsiveness if invoked on the main thread. Instead, consider waiting for the -locationManagerDidChangeAuthorization: callback and checking authorizationStatus first." I have 2 questions: What is that error about, really? The locationServicesEnabled() has nothing to do with authorisation, it's just about the "location services" settings global on-off switch? (the authorisation check is .authorizationStatus) I don't understand why that call is such a big issue? It's just a setting? Why would that be so costly? Thankful for pointers! Have a good one
5
0
507
Sep ’24
How can I get something similar to launchOptions[UIApplication.LaunchOptionsKey.location] in SceneDelegate for iOS 13+ apps
I'm making an app for iOS 13+ devices. My project has both app delegate and scene delegate files. I'm using core location for significant location changes. I was able to detect significant location changes and system waking up my app in simulator using SignificantlyChanged app’s scheme. But when the launch options dictionary has 0 elements and the value for the key UIApplication.LaunchOptionsKey.location is always nil. Here is my AppDelegate.swift where the system will launch the app in background state when a significant location change is detected and execute the location fetch code. And location manager class. I want to know if the app is launched my the system or if it is launched by the user so I want to check if UIApplication.LaunchOptionsKey.location key has a value. But it is always nil and there is no alternative to it in SceneDelegate. When and how can I find a solution to this long due issue. import CoreLocation @main class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. if launchOptions != nil{ if launchOptions![UIApplication.LaunchOptionsKey.location] != nil{ print("Called from background location fetch") } } LocationService.shared.askForPermission() LocationService.shared.delegate = self return true } // MARK: UISceneSession Lifecycle func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { // Called when a new scene session is being created. // Use this method to select a configuration to create the new scene with. return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) } func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) { // Called when the user discards a scene session. // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. // Use this method to release any resources that were specific to the discarded scenes, as they will not return. } } extension AppDelegate: LocationMangerDelegate{ func didFetchLocation(coordinate: CLLocationCoordinate2D) { print(coordinate) } func didFailToFetchLocation(error: Error?, message: String) { print(message) } }``` import Foundation import CoreLocation protocol LocationMangerDelegate: AnyObject{ func didFetchLocation(coordinate: CLLocationCoordinate2D) func didFailToFetchLocation(error: Error?,message: String) } class LocationService: NSObject{ private override init() { } weak var delegate: LocationMangerDelegate? static var shared = LocationService() lazy var locationManager: CLLocationManager = { var manager = CLLocationManager() manager.desiredAccuracy = kCLLocationAccuracyBest manager.allowsBackgroundLocationUpdates = true manager.pausesLocationUpdatesAutomatically = false manager.delegate = self return manager }() func askForPermission(){ print("INSIDE") locationManager.requestWhenInUseAuthorization() } func startLocationUpdates(){ self.locationManager.startUpdatingLocation() } func stopLocationUpdates(){ self.locationManager.stopUpdatingLocation() } } extension LocationService: CLLocationManagerDelegate{ func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) { let status = manager.authorizationStatus switch status { case .notDetermined: self.askForPermission() case .restricted: self.delegate?.didFailToFetchLocation(error: nil, message: "Location permission is restricted by the user") case .denied: self.delegate?.didFailToFetchLocation(error: nil, message: "Location permission is denied by the user") case .authorizedWhenInUse: self.locationManager.requestAlwaysAuthorization() case .authorizedAlways: self.locationManager.startMonitoringSignificantLocationChanges() @unknown default: break } } func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { if let location = locations.first{ print(location) self.delegate?.didFetchLocation(coordinate: location.coordinate) self.stopLocationUpdates() } } func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) { print(error) self.delegate?.didFailToFetchLocation(error: error, message: error.localizedDescription) } }
1
0
384
Aug ’24
Did WeatherKit minutely precipitation intentionally change units?
I've noticed in the past few weeks that the minutely precipitation values reported by WeatherKit are much bigger than they were before. Specifically I'm referring to WeatherKit.MinuteWeather.precipitationIntensity. In my app, I convert to mm per hour: let mmPerHour = $0.precipitationIntensity.converted(to: UnitSpeed.kilometersPerHour).value * 1e6 This has worked perfectly since WeatherKit came out, but now when I look at rainy locations and compare with the built-in Apple Weather app on my phone, it seems that the new values are about 3x what they should be. I have checked this in multiple locations across the USA. My intuition says this is an inches/cm conversion issue (2.54x). Is this an intentional change in WeatherKit that requires me to update my app, or is this a bug on Apple's end??
2
0
346
Aug ’24
MKScaleView doesn't update changing area programmatically
I have a MKMapView with a MKScaleView. If I visualise a generic map I have the scale in km. When I change the MKMapRect using visibleMapRect, the scale doesn't change. If I use setVisibleMapRect(_ mapRect: MKMapRect, animated animate: Bool), the scale change but not to the correct one. For example, it shows a scale saying one inch corresponds to 250 m while it is 150 m. The same issue of I use MKCoordinateRegion. Instead, if I zoom in or zoom out pinching on the map, the scale updates correctly. Am I doing something wrong? How can I fix this? Sample code: import UIKit import MapKit let CORNER_RADIUS: CGFloat = 8.0 let METERS_PER_MILE: Double = 1609.344 class PIAnnotation: NSObject, MKAnnotation { var coordinate: CLLocationCoordinate2D private(set) var title: String? private(set) var subtitle: String? init(location: CLLocationCoordinate2D, title: String? = nil, subtitle: String? = nil) { coordinate = location self.title = title self.subtitle = subtitle } } class PISimpleMapView: MKMapView { private let HALF_MAP_SIDE_MULTIPLIER: Double = 1.4 private let pinIdentifier = "pinIdentifier" private var scaleView: MKScaleView? typealias PinAnnotationView = MKMarkerAnnotationView // MKPinAnnotationView required init?(coder: NSCoder) { super.init(coder: coder) inizialize() } override init(frame: CGRect) { super.init(frame: frame) inizialize() } func inizialize() { layer.cornerRadius = CORNER_RADIUS register(PinAnnotationView.self, forAnnotationViewWithReuseIdentifier: pinIdentifier) addScale() } private func addScale() { let scale = MKScaleView(mapView: self) scale.translatesAutoresizingMaskIntoConstraints = false scale.scaleVisibility = .visible // always visible addSubview(scale) let guide = safeAreaLayoutGuide NSLayoutConstraint.activate([ scale.leftAnchor.constraint(equalTo: guide.leftAnchor, constant: 16.0), scale.rightAnchor.constraint(equalTo: guide.centerXAnchor), scale.topAnchor.constraint(equalTo: guide.topAnchor), scale.heightAnchor.constraint(equalToConstant: 20.0) ]) scaleView?.removeFromSuperview() scaleView = scale } func displayPinOnMap(location: CLLocation) { let annotation = PIAnnotation(location: location.coordinate, title: "Sample", subtitle: nil) addAnnotation(annotation) // Position the map so that all overlays and annotations are visible on screen. visibleMapRect = visibleArea(from: annotation) // setVisibleMapRect(visibleArea(from: annotation), animated: true) // region = MKCoordinateRegion(visibleArea(from: annotation)) } private func visibleArea(from annotation: PIAnnotation) -> MKMapRect { let annotationPoint = MKMapPoint(annotation.coordinate) return MKMapRect(x: annotationPoint.x - HALF_MAP_SIDE_MULTIPLIER * METERS_PER_MILE, y: annotationPoint.y - HALF_MAP_SIDE_MULTIPLIER * METERS_PER_MILE, width: HALF_MAP_SIDE_MULTIPLIER * 2.0 * METERS_PER_MILE, height: HALF_MAP_SIDE_MULTIPLIER * 2.0 * METERS_PER_MILE) } }
5
0
467
Aug ’24
Apple MapKit Js Token update
I might be being really ******, but I'm struggling to find a way to update the map kit token when it expires. We have a display that shows a map for a long time and for some reason the map stops loading and I think it's cause the token expires however I can't work out away to tell it to load a new token.
1
0
321
Aug ’24
hello, where can I find the supporting file "info.plist" in xcode?
I always get the user location not found error even though I have activated my location import SwiftUI import MapKit import CoreLocation class LocationManager: NSObject, ObservableObject, CLLocationManagerDelegate { private let locationManager = CLLocationManager() @Published var location: CLLocation? = nil @Published var authorizationStatus: CLAuthorizationStatus? = nil override init() { super.init() locationManager.delegate = self locationManager.desiredAccuracy = kCLLocationAccuracyBest locationManager.requestWhenInUseAuthorization() locationManager.startUpdatingLocation() } func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { guard let newLocation = locations.last else { return } location = newLocation print("Updated location: \(newLocation.coordinate.latitude), \(newLocation.coordinate.longitude)") } func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) { authorizationStatus = status if status == .authorizedWhenInUse || status == .authorizedAlways { locationManager.startUpdatingLocation() } } } private func sectionTitle(_ title: String) -> some View { Text(title) .font(.headline) .fontWeight(.bold) .padding(.bottom, 8) } private func openAppleMaps() { let destinationLatitude: CLLocationDegrees = -6.914744 let destinationLongitude: CLLocationDegrees = 107.609810 guard let currentLocation = locationManager.location?.coordinate else { print("Lokasi pengguna tidak ditemukan.") return } let currentLatitude = currentLocation.latitude let currentLongitude = currentLocation.longitude // URL encode parameters let urlString = "http://maps.apple.com/?saddr=\(currentLatitude),\(currentLongitude)&daddr=\(destinationLatitude),\(destinationLongitude)&dirflg=d" guard let appleMapsUrl = URL(string: urlString) else { print("URL tidak valid.") return } // Open Apple Maps UIApplication.shared.open(appleMapsUrl, options: [:]) { success in if !success { print("Gagal membuka Apple Maps.") } } }
1
0
348
Aug ’24
Loading large amounts of coordinates and annotations to a map?
My query might return 20,000 coordinates. Does MapKit JS try to load all the coordinates at once into the map or does it only load what’s in the viewport of the map if we were to load 20,000 annotations into the say something like “landmark data” const? We have 900,000 coordinates to load into Los Angeles and are planning how we will do this. Obviously we can’t load 900,000 coordinates at once without performance issues, but some query’s return 20,000 results. Can someone point me to some information about large datasets and MapKit js or let me know if it’s handled and already built in to not try to load that many locations at once?
0
0
328
Aug ’24
MapKit JS API not loading
I own a website (timeguessr.com) that uses the apple mapkit js api. I have had a number of reports in the last few weeks of users having the map not loading. Since I have not been able to recreate the problem I have asked people to send screenshots of what is logged to their developer tools console. In each case a ERR_HTTP2_PROTOCOL_ERROR 200 (OK) error is being logged when the user is trying to fetch from cdn.apple-mapkit.com endpoints. What is strange is this happens halfway through their games when they have already successfully loaded the map in previous rounds. Can anyone help? Thanks
1
0
505
Aug ’24
Push Location Service Entitlement
Hello! Back on April 4th our team requested the push location service entitlement. Our app requires very similar background tracking as Find my or Life 360 where users agree to share locations and another user might want to prompt for an update. Since submitting on April 4th, we have received no response or update from our request. I've called and emailed with developer support 20+ separate times (They've escalated it at least 10 times at this point) with no response either. I've also submitted new requests in case our original got lost. Is there anyone else we can contact or talk with to get any progress? The developer support team is even at a loss for how long this is taking now. We are just completely lost on what our next step could be
1
1
327
Aug ’24
How can I ensure that the GNSS received on iOS is reliable at the decimeter to centimeter level?
I am trying to use GNSS data to track the location of a mobile phone with high precision. I understand that using Fused Location provided by iOS can improve accuracy, but it is not perfect. To inform the user when the current GNSS location is somewhat inaccurate (with meter-level error), which data fields should I rely on? (e.g., horizontal accuracy, vertical accuracy) Additionally, I am curious if iOS currently supports dual-band GNSS calculations (e.g., SBAS, BeiDou-3, etc.). If supported, which API can be used to determine this status?
1
0
400
Aug ’24
Swift 6 Concurrency Errors with MKLocalSearchCompleterDelegate results
Has anyone found a thread-safe pattern that can extract results from completerDidUpdateResults(MKLocalSearchCompleter) in the MKLocalSearchCompleterDelegate ? I've downloaded the code sample from Interacting with nearby points of interest and notice the conformance throws multiple errors in Xcode 16 Beta 5 with Swift 6: extension SearchDataSource: MKLocalSearchCompleterDelegate { nonisolated func completerDidUpdateResults(_ completer: MKLocalSearchCompleter) { Task { let suggestedCompletions = completer.results await resultStreamContinuation?.yield(suggestedCompletions) } } Error: Task-isolated value of type '() async -> ()' passed as a strongly transferred parameter; later accesses could race and Error: Sending 'suggestedCompletions' risks causing data races Is there another technique I can use to share state of suggestedCompletions outside of the delegate in the code sample?
2
1
970
Aug ’24
CarPlay Map Displays White Screen
Hello, I'm somewhat new to CarPlay integration and am having an issue. I have ready through Apple's CarPlay Programming Guide, reviewed their code samples and have exhausted my searches online to help find a solution to my problem. I have been unable to get a basic map to display on my CarPlay map utilizing the following: import CarPlay class CarPlaySceneDelegate: UIResponder, CPTemplateApplicationSceneDelegate { var interfaceController: CPInterfaceController? var window: CPWindow? func templateApplicationScene(_ templateApplicationScene: CPTemplateApplicationScene, didConnect interfaceController: CPInterfaceController) { self.interfaceController = interfaceController let mapTemplate = CPMapTemplate() mapTemplate.mapDelegate = self interfaceController.setRootTemplate(mapTemplate, animated: true, completion: { success, error in if let error = error { debugPrint("Error: \(error)") } else { print("CarPlay Map Should Be Displayed") } }) let trip = CPTrip(origin: MKMapItem(placemark: .init(coordinate: CLLocationCoordinate2D(latitude: 0.0, longitude: 0.0))), destination: MKMapItem(placemark: .init(coordinate: CLLocationCoordinate2D(latitude: 0.0, longitude: 0.0))), routeChoices: []) mapTemplate.startNavigationSession(for: trip) } } extension CarPlaySceneDelegate: CPMapTemplateDelegate { func mapTemplate(_ mapTemplate: CPMapTemplate, panWith direction: CPMapTemplate.PanDirection) { // Handle panning } func mapTemplate(_ mapTemplate: CPMapTemplate, startedTrip trip: CPTrip, using routeChoice: CPRouteChoice) { // Handle trip start } } I have my CarPlay Entitlements setup, I have my CarPlay Navigation App set in my signing and capabilities and my app icon displays properly on CarPlay (both in simulator and inside of my vehicle). However, as mentioned I only get a white screen. Now, if I utilize the following code, I will get my map to display, however I lose functionality such as panning the map. I'm sure that I am missing something simple on the above example and appreciate any guidance that you may have. func createMapTemplate(destination: TripDetails?, destinationBL: BucketListItems?, route: MKRoute, window: UIWindow) -> CPMapTemplate { mapTemplate = CPMapTemplate() mapTemplate.mapDelegate = self trip = nil let startLocation = CLLocation(latitude: location.coordinate.latitude, longitude: location.coordinate.longitude) let startMapItem = MKMapItem(placemark: MKPlacemark(coordinate: startLocation.coordinate)) startMapItem.name = "Starting Location" let endMapItem = MKMapItem(placemark: MKPlacemark(coordinate: route.polyline.points()[route.polyline.pointCount - 1].coordinate)) endMapItem.name = destination?.campgroundName != nil ? destination!.campgroundName : destinationBL!.name // Create the hosting controller for the SwiftUI view let mapViewController = UIHostingController(rootView: CarPlayMapView(templateManager: self)) window.rootViewController = mapViewController window.makeKeyAndVisible() let routeChoice = createCPRouteChoice(from: route) trip = CPTrip(origin: startMapItem, destination: endMapItem, routeChoices: [routeChoice]) mapTemplate(mapTemplate, selectedPreviewFor: trip!, using: routeChoice) mapTemplate.showTripPreviews([trip!], textConfiguration: nil) return mapTemplate }
1
0
380
Aug ’24