Build maps and location awareness capabilities into your apps.

All subtopics
Posts under Maps and Location topic

Post

Replies

Boosts

Views

Activity

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
542
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
557
Nov ’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
462
Nov ’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
431
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
540
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://*******.com/3fu88jwj might help solve your issue. If you still need help, please open a support ticket by copying and pasting this link: https://*******.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
596
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
488
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
761
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
726
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
400
Dec ’24
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
1.9k
Dec ’24
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
575
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
447
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
326
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
482
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
883
Jan ’25
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
406
Jan ’25
iOS location recording issues iOS 18
I’m facing an issue with iOS that I hope someone can help with. I developed an app a few years ago that records GPS tracks. Up until recently, everything worked fine—even when the app was running in the background, the recording continued without problems. However, since releasing an update compiled after the iOS 18 release, users have reported that background tracking no longer works. I’ve reviewed the iOS documentation but haven’t found any relevant changes or solutions. Before the newly compiled release the app was working well on iOS 18 devices as well. Some users have reported that switching to the location permission from "When Using the App" to "Always" solved the issue. This is not the case for all users. Has anyone else encountered this issue? Any recommendations or insights on how to resolve it would be greatly appreciated. Below you can see the code used for the location tracking. Before the issue happened the app was compiled with XCode 15.4. Now I am using XCode 16.2 locationManager.activityType = CLActivityType.fitness locationManager.desiredAccuracy = kCLLocationAccuracyBest locationManager.distanceFilter = 3 locationManager.allowsBackgroundLocationUpdates = true locationManager.pausesLocationUpdatesAutomatically = false if #available(iOS 11.0, *) { locationManager.showsBackgroundLocationIndicator = true } locationManager.startUpdatingLocation() if #available(iOS 17.0, *) { // Create a CLBackgroundActivitySession object backgroundActivitySession = CLBackgroundActivitySession() } Thanks in advance for your help!
3
2
569
Feb ’25