Build maps and location awareness capabilities into your apps.

All subtopics
Posts under Maps and Location topic

Post

Replies

Boosts

Views

Created

SwiftUI MapKit use of UserLocation struct
I have a map where I am using UserAnnotation() to show the user's location. Location permissions are handled elsewhere in the app. If the user has previously granted location permission, that is enough for the UserAnnotation() blue pin to appear. Otherwise, it just doesn't draw. So the Map already knows the user's permission and location without my code again requesting location etc. I was looking for a way to leverage the map's knowledge of the user's location and came across this struct as described in the Documentation for SwiftUI Mapkit public struct UserLocation { public var heading: CLHeading? public var location: CLLocation? } I thought this struct might expose the user's location, but how it is expected to be used or when it should populated is unknown from the point of the documentation. Would someone please share the purpose and use of this struct?
1
1
432
Jan ’25
iOS 18: “Settings” button on location permission alert does nothing, logs BUG IN CLIENT OF UIKIT warning
Hello everyone, I’m encountering a problem on the latest iOS 18 related to location permissions. When the user denies location access, my app triggers the standard system prompt asking them to enable location from Settings. On iOS 17 and below, tapping the “Settings” button in this system alert would successfully navigate the user to my app’s Settings page. However, on iOS 18, nothing happens. Instead, I see the following warning in the Xcode console: Warning : BUG IN CLIENT OF UIKIT: The caller of UIApplication.openURL(:) needs to migrate to the non-deprecated UIApplication.open(:options:completionHandler:). Force returning false (NO). Important details and context: In my own code, I have already replaced all calls to openURL(:) with open(:options:completionHandler:). I searched the entire codebase for usage of openURL: and didn’t find any. The alert that appears is the system location alert (iOS-generated), not a custom UIAlertController. Thus, I have no direct control over the underlying call. On iOS 17 (and below), tapping “Settings” in the same system dialog works perfectly and takes the user to the app’s permission page. The console message implies that somewhere—likely inside the system’s own flow—the deprecated API is being called and blocked on iOS 18. What I’ve tried: Verified I am not calling openURL: anywhere in my code. Confirmed that UIApplication.openSettingsURLString works when I programmatically open it in a custom alert. Tested multiple times on iOS 17 and iOS 18 to confirm the behavior difference. Steps to reproduce: Install the app on a device running iOS 18 Beta. Deny location permission when prompted. Trigger a piece of code that relies on location (e.g., loading a map screen) so that the OS automatically shows its standard “Location is disabled” alert, which includes a “Settings” button. Tap “Settings.” On iOS 17, this navigates to the app’s Settings. On iOS 18 Beta, it does nothing, and the console logs the BUG IN CLIENT OF UIKIT warning. Questions: Is this a known iOS 18 bug where the system’s own alert is still using the deprecated openURL: call? If so, are there any workarounds besides presenting a custom alert that manually calls open(_:options:completionHandler:)? Thank you in advance. Any guidance or confirmation would be appreciated!
1
1
956
Jan ’25
How to correct business location?
My organization, Los Angeles Pierce College, rents space to "Topanga Vintage Market", which is a monthly weekend swap meet operation. Apple Maps shows the location as roughly 34.18715° N, 118.58058° W. However, this is the location of the campus Child Development Center, which provides child care services and is not open during the hours of the Topanga Vintage Market. The actual location should be in the adjacent large parking lot, roughly 34.18740° N, 118.57782° W. They do not have a physical building. How do I get this resolved? I am putting a campus mapping application into the App Store real soon now. There is also an entry for "ALC Taco Truck" about 34.18533° N, 118.57349° W, which as far as I know has not been on campus since Covid. Thanks in advance for any guidance you can provide.
1
0
523
Jan ’25
Location Push Service Extension in Limbo
Hi everyone, I submitted a request for the Location Push Service Extension entitlement back in November. I received an acknowledgment email from Apple confirming they had received my request, but I never heard back. Assuming the November request might have been lost in the shuffle, I submitted another request in January. It's been a week since then, and I still haven’t received any response. To follow up, I contacted Apple Support with my case number. Unfortunately, it seems they didn’t review the case properly, as the support assistant just sent me generic links about what to do when an app is rejected—which doesn’t apply here. Has anyone else experienced similar delays with this entitlement? Could there be specific reasons for such delays? Any tips on how to escalate this or get it addressed effectively would be greatly appreciated. Thank you in advance for your help!
0
0
343
Jan ’25
Documentation of parameters to enable Apple Maps EV routing
Hi, I'm building an aftermarket solution to enable Apple Maps to support EV routing for any EV. I am going through the documentation and found some gaps - does anyone know how the following properties work? INGetCarPowerLevelStatusIntentResponse - consumptionFormulaArguments INGetCarPowerLevelStatusIntentResponse - chargingFormulaArguments Is there a working example that anyone has seen? Many thanks
2
0
472
Jan ’25
New CoreLocation APIs
Hi All, I am currently working on an app that has some navigation functionality, and since my minimum iOS is 18 wanted to incorporate the new APIs that yield a AsyncStream of locations. I have watched both WWDC sessions, the one where the new API is introduced to retrieve the location points, and also the other video where the new authorization process for location is simplified as well. I have an app currently working in its current state, but am noticing some weird quirks when using the CLBackgroundActivitySession to get the elevated background permission. What I am doing here is to create this stream and the background object is below: return AsyncThrowingStream { continuation in let task = Task { do { for try await update in CLLocationUpdate.liveUpdates(updateType) { if shouldStopUpdate { continuation.finish() break } continuation.yield(update) } } catch { continuation.finish(throwing: error) } } state = .started(locationTask: task, background: CLBackgroundActivitySession()) } When I have an active navigation session going and am strongly holding this object and the user force quits the app (or I stop the target through Xcode) the navigation activity indicator in the status bar (or dynamic island) remains present. Even if I relaunch the app, start navigation again, and then call the invalidate method on the CLBackgroundActivitySession I then am seeing that navigation indicator even if I delete my app, and often need to do a full restart to get out of this state. Is there a step I am missing, or do I not understand the way the new API works to run in the background?
1
0
617
Jan ’25
Warnings - Failed to locate resource
I have a test application I'm working on (so it's a fresh Xcode project under Sonoma - with older map code borrowed from another project). It is a macOS application. And in Obj-C. When the map window is opened the logs contain the following - I've been trying to hunt down and resolve. Thank you in advance for any clues/pointers. Failed to locate resource "default.csv" Failed to locate resource "satellite@2x.styl" Failed to locate resource "satellite@2x.styl" Failed to locate resource "satellite.styl" Failed to locate resource "satellite@2x.styl" Failed to locate resource "satellite@2x.styl" Failed to locate resource "satellite.styl" Failed to locate resource "satellite.styl" Couldn't find satellite.styl in framework, file name satellite.styl Authorization status: Authorized The application does have MapKit.framework included.
4
1
2k
Dec ’24
App Clip Not Launching From Approved Apple Maps Action Link
We’ve set up an advanced App Clip experience that successfully launches when a user scans our QR code. However, the same App Clip invocation URL does not launch when tapping the associated Action Link on our Apple Place Card in Apple Maps. Instead of opening the App Clip, the link falls back to the website. What We Have Done So Far: App Clip Launched in App Store Connect: Our App Clip is approved and live on the App Store. Here is the invocation URL: https://appclip.parkzenapp.com/park?q=oJrbSIgx Below is the QR code for our Advanced App Clip experience we are attempting to open in our Apple Maps Place card When scanning the QR code that uses the same App Clip invocation URL, the App Clip reliably launches as expected. Here is our apple-app-site-association file, thats correctly served from the associated domain: https://appclip.parkzenapp.com/.well-known/apple-app-site-association Add here is a screenshot showing how the appclip.parkzenapp.com domain is correctly validated. Advanced App Clip Experience: We created and submitted an advanced App Clip Experience specifically tied to our location on Apple Maps. This App Clip Experience is approved and live. Below is an image of our set up of this Advanced App Clip Experience Business Connect: We've created the Apple Maps Location in business connect and added the advanced App Clip experience invocation URL as an Action Link in the place card. See screenshot below. Apple Maps Place: https://maps.apple.com/place?auid=906421750045811407 Despite meeting these conditions, when a user taps the Action Link (the "Reserve" button in the Apple Maps Place Card), the fallback website opens rather than the App Clip. Question: What additional step or configuration might we be missing to ensure the Action Link on our Apple Maps place card triggers the App Clip instead of the website? Thank you
0
0
437
Dec ’24
How to search location in global rather than in local?
I'm doing a weather app, users can search locations for getting weather, but the problem is, the results only shows locations in my country, not in global. For example, I'm in China, I can't search New York, it just shows nothing. Here's my code: @Observable class SearchPlaceManager: NSObject { var searchText: String = "" let searchCompleter = MKLocalSearchCompleter() var searchResults: [MKLocalSearchCompletion] = [] override init() { super.init() searchCompleter.resultTypes = .address searchCompleter.delegate = self } @MainActor func seachLocation() { if !searchText.isEmpty { searchCompleter.queryFragment = searchText } } } extension SearchPlaceManager: MKLocalSearchCompleterDelegate { func completerDidUpdateResults(_ completer: MKLocalSearchCompleter) { withAnimation { self.searchResults = completer.results } } } Also, I've tried to set searchCompleter.region = MKCoordinateRegion( center: CLLocationCoordinate2D(latitude: 0, longitude: 0), span: MKCoordinateSpan(latitudeDelta: 180, longitudeDelta: 360) ), but it doesn't work.
2
0
758
Dec ’24
React native expo background location send to firebase
Hi, I have develop the application in the react native. Now this application is related to truck drivers. So we have added load and when they accept the load then we fetch the location to firebase. Now issue is its not working when app close (background) on physical device. We tried on simulator and its working perfectly in the background. But when i make the build and test on physical device its not working for background task.
2
0
776
Dec ’24
didEnterRegion and didExitRegion delegate methods are called twice
When I set the values of notifyOnExit and notifyOnEnter to true when registering CLCircularRegion, I checked that the didExitRegion and didEnterRegion functions are called well. However, there is a problem that they are called twice in a row every time they are called. I was wondering if this is an internal bug in the API. There is also a stackoverflow report related to the above issue. I would appreciate your confirmation. stackoverflow - why the didEnterRegion called twice? Thank you.
1
0
513
Dec ’24
IOS 18 is blocking GPS connectivity for Waze/Google Maps…
On IOS 18, starting October this year, the location is not syncing in real time.You might drive for several kilometers and the location displayed on Waze will remain on the same position.This might put in position to miss the exit on the highway and have to drive another 40/50 km, lose time and energy, to get back in the original track. Reinstall the application twice is not correcting the behavior, as well as changing the device, the same issue is present on iPhone 16. Waze support team shared the following: ”Hey there! We'd like to apologize for any hassle that this has caused you. This article: https://tinyurl.com/3fu88jwj might help solve your issue. If you still need help, please open a support ticket by copying and pasting this link: https://tinyurl.com/mrx77ukz in a web browser, and someone from the team will get back to you soon." Based on the above facts, this is clearly an IOS 18 issue, that needs to be prioritized.
2
0
650
Dec ’24
Requirement of location services to prevent fake orders
Hi all, I have a delivery app that requires the user's location on start up. For example to determine the list of services available to the user. So on start up the app asks for location permission. While the app does have a concept of creating addresses, we still require location services so that the user can only select an address close to their current GPS. This is done to prevent fake orders, many apps with similar functionality allow you to pick any location on the map even if you decline location services, which in turn causes a lot of trouble since there are constantly fake orders being created. So to counter that we're asking for the user's location. Now my question is: will apple force me to absolutely never require location access or will explaining to them the problem of fake orders allow me to pass the review? Another feature I have is a driving mode, it's a map for drivers to see routes to a specific order. Obviously I need location services for that to function, or will Apple's review team also cling to that and force me to implement some weird way of letting the user choose their current location? Because there are a lot of trolls that create fake orders, and then have 20 delivery drivers come to a place in a middle of a road. This is a serious issue and will literally kill our business if not countered somehow.
2
0
558
Dec ’24
Deriving Apple Place ID from CLPlacemark or MKMapItem
I am trying to derive the Apple Place ID from a CLPlacemark (or via a MKMapItem derived from it) created via either CLGeocoder().reverseGeocodeLocation() or CLGeocoder().geocodeAddressString(). In many cases, the placemark returned from these functions contains detailed information (name, address, coordinates, etc), implying that the Apple Place ID is known, but the identifier is not present. The only way I have found to get a Place ID is via MKLocalSearch. Wondering if I am missing something here.
2
1
460
Dec ’24
iOS 18 MapKit discrepancy between physical devices and simulators
I have noticed a discrepancy between behavior on physical devices and simulators in iOS 18. I am using the latest MapKit APIs to fetch MKMapItems using the following MKLocalSearch: private func performLocalSearch(_ query: String) async throws -> [MKMapItem] { let request = MKLocalSearch.Request() request.naturalLanguageQuery = query let search = MKLocalSearch(request: request) return try await search.start().mapItems } This returns an array of MKMapItem on both the simulator and physical device. The key difference is my physical device (iOS 18.1.1) is missing the MKMapItem's identifier value. On the simulator, identifier is always populated in addition to my search. Any ideas on how to resolve this? The new MapKit API for those curious: @available(iOS 6.0, *) open class MKMapItem : NSObject { @available(iOS 18.0, *) open var identifier: MKMapItem.Identifier? { get }
1
0
479
Nov ’24
UIViewRepresentable & MVVM
I am trying to get my head around how to implement a MapKit view using UIViewRepresentable (I want the map to rotate to align with heading, which Map() can't handle yet to my knowledge). I am also playing with making my LocationManager an Actor and setting up a listener. But when combined with UIViewRepresentable this seems to create a rather convoluted data flow since the @State var of the vm needs to then be passed and bound in the UIViewRepresentable. And the listener having this for await location in await lm.$lastLocation.values seems at least like a code smell. That double await just feels wrong. But I am also new to Swift so perhaps what I have here actually is a good approach? struct MapScreen: View { @State private var vm = ViewModel() var body: some View { VStack { MapView(vm: $vm) } .task { vm.startWalk() } } } extension MapScreen { @Observable final class ViewModel { private var lm = LocationManager() private var listenerTask: Task<Void, Never>? var course: Double = 0.0 var location: CLLocation? func startWalk() { Task { await lm.startLocationUpdates() } listenerTask = Task { for await location in await lm.$lastLocation.values { await MainActor.run { if let location { withAnimation { self.location = location self.course = location.course } } } } } Logger.map.info("started Walk") } } struct MapView: UIViewRepresentable { @Binding var vm: ViewModel func makeCoordinator() -> Coordinator { Coordinator(parent: self) } func makeUIView(context: Context) -> MKMapView { let view = MKMapView() view.delegate = context.coordinator view.preferredConfiguration = MKHybridMapConfiguration() return view } func updateUIView(_ view: MKMapView, context: Context) { context.coordinator.parent = self if let coordinate = vm.location?.coordinate { if view.centerCoordinate != coordinate { view.centerCoordinate = coordinate } } } } class Coordinator: NSObject, MKMapViewDelegate { var parent: MapView init(parent: MapView) { self.parent = parent } } } actor LocationManager{ private let clManager = CLLocationManager() private(set) var isAuthorized: Bool = false private var backgroundActivity: CLBackgroundActivitySession? private var updateTask: Task<Void, Never>? @Published var lastLocation: CLLocation? func startLocationUpdates() { updateTask = Task { do { backgroundActivity = CLBackgroundActivitySession() let updates = CLLocationUpdate.liveUpdates() for try await update in updates { if let location = update.location { lastLocation = location } } } catch { Logger.location.error("\(error.localizedDescription)") } } } func stopLocationUpdates() { updateTask?.cancel() updateTask = nil } func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) { switch clManager.authorizationStatus { case .authorizedAlways, .authorizedWhenInUse: isAuthorized = true // clManager.requestLocation() // ?? case .notDetermined: isAuthorized = false clManager.requestWhenInUseAuthorization() case .denied: isAuthorized = false Logger.location.error("Access Denied") case .restricted: Logger.location.error("Access Restricted") @unknown default: let statusString = clManager.authorizationStatus.rawValue Logger.location.warning("Unknown Access status not handled: \(statusString)") } } func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) { Logger.location.error("\(error.localizedDescription)") } }
1
0
610
Nov ’24
CLCircularGeographicCondition 20 Condition Limit
According to the following article, the CLCircularGeographicCondition has a limit whereby only 20 conditions can be monitored by any single app. Monitoring the user’s proximity to geographic regions While I understand the rationale behind this limit, 20 conditions seems quite low for some apps. It would be good if an app could request that the user opt-in to allowing more conditions if they understand the impact this might have on the battery etc. I'm migrating an app presently to use CLCircularGeographicCondition instead of the now deprecated CLCircularRegion. It would be good if there were more guidance on how to use the new Core Location API's to monitor how many conditions are in use within an app and how they can be deactivated when no longer required, allowing the app to free up more of the 20 conditions available.
2
0
568
Nov ’24
Clarification needed regarding requirements for geofencing
In my app, I am using geofencing to perform an action when the user enter or leaves a specified location. The geofencing (CLMonitor) is active permanently, and should work across multiple app sessions or after the device is restarted. It should also work after the app was minimized or terminated. This worked perfectly with iOS 17 and prior, but with iOS 18, things changed. As soon as iOS 18 dropped, users were informing me that the app does no longer perform the entry/exit action reliably (without me making any changes to the app). Most of the times, events are missed entirely. Sometimes, after the user opens or resumes the app, duplicate events are delivered and/or events with the current time instead of the correct time of entry/exit. I am making sure that the app has the "Always" location permission before geofencing is enabled The gefocence radius is between 20 and 500m, but even with the max. radius specified, the geofencing is unreliable For the same user and geofence, the entry/exit event is delivered occasionally, but not always I am currently not using CLLocationManager.allowsBackgroundLocationUpdates (even though it's documented as "Apps that receive location updates when running in the background must include the UIBackgroundModes key (with the location value) in their app’s Info.plist file") because it wasn't necessary on iOS 17 and in my tests, using it didn't yield any improvements In my search for what could have caused this change, I found this WWDC video about location authorization: . It appears that with iOS 18, it is now required to have an active CLServiceSession to ensure that location updates are delivered to my app. Even though the video is long (and I've watched it multiple times), some things are still unclear. For example, the docs state: If your app actively receives and processes location updates and terminates, it should restart those APIs upon launch in order to continue receiving updates. Also, in the video it is stated that: ... So your job, ..., is to make sure that your process launch logic knows what features it has been tasked with pursuing, and re-takes session objects... But on the other hand it's also said that: you can only start holding one (a CLServiceSession) when your app is in the foreground and also ... CLMonitor.events won’t yield results when it is not in use, unless a session which was started in the foreground, .... To summarize my questions, for the geofencing to work as described above: when exactly do I need to create a CLServiceSession if the app is launched into the backgorund? Immediately in the applicationDidFinishLaunching method, even though the app is still in the background (applicationState is background)? Or later on, when the app is opened again by the user, e.g. in applicationDidBecomeActive (and applicationState is active)? do I need to specify the background mode capability as noted in the Handling location updates in the background article? do I need to create a CLBackgroundActivitySession as noted in the Handling location updates in the background article? does it matter, which of the four initializer methods I am using to create the CLServiceSession (with CLServiceSessionAuthorizationRequirementAlways)? does it matter if I specify NSLocationRequireExplicitServiceSession in the Info.plist or not when I already do ensure that the app has the "Always" location permission when the feature is being enabled Does a CLServiceSession last indefinitely and should it only be invalidated once the user disables the feature?
3
7
953
Nov ’24