Hi,
I have been working with an implementation of MapKit which show custom annotations with a detailCalloutAccessoryView built using SwiftUI. This has been working fine for many years, but starting with macOS Tahoe, somehow the SwiftUI buttons in this view have stopped being tappable.
I have reproduced the issue in the code below ... same code works fine in macOS14 and macOS15 now doesn't work correctly in macOS26:
import Cocoa
import MapKit
import SwiftUI
class ViewController: NSViewController {
private var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
setupMapView()
}
private func setupMapView() {
// Create and configure the map view
mapView = MKMapView()
mapView.translatesAutoresizingMaskIntoConstraints = false
mapView.delegate = self
view.addSubview(mapView)
// Pin the map to all edges of the view
NSLayoutConstraint.activate([
mapView.topAnchor.constraint(equalTo: view.topAnchor),
mapView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
mapView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
mapView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
])
// Create an annotation for San Francisco
let sanFranciscoCoordinate = CLLocationCoordinate2D(latitude: 37.7749, longitude: -122.4194)
let annotation = MKPointAnnotation()
annotation.coordinate = sanFranciscoCoordinate
annotation.title = "San Francisco"
annotation.subtitle = "The City by the Bay"
// Add the annotation to the map
mapView.addAnnotation(annotation)
// Center the map on San Francisco
let region = MKCoordinateRegion(center: sanFranciscoCoordinate,
latitudinalMeters: 5000,
longitudinalMeters: 5000)
mapView.setRegion(region, animated: false)
}
}
// MARK: - MKMapViewDelegate
extension ViewController: MKMapViewDelegate {
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
let identifier = "CustomAnnotation"
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier) as? MKMarkerAnnotationView
if annotationView == nil {
annotationView = MKMarkerAnnotationView(annotation: annotation, reuseIdentifier: identifier)
annotationView?.canShowCallout = true
// Create the SwiftUI view for the callout
let calloutView = CalloutContentView()
let hostingView = NSHostingView(rootView: calloutView)
hostingView.frame = NSRect(x: 0, y: 0, width: 200, height: 100)
// Set the SwiftUI view as the detail callout accessory
annotationView?.detailCalloutAccessoryView = hostingView
} else {
annotationView?.annotation = annotation
}
return annotationView
}
}
// MARK: - SwiftUI Callout View
struct CalloutContentView: View {
var body: some View {
VStack(spacing: 12) {
Text("Welcome to San Francisco!")
.font(.headline)
.multilineTextAlignment(.center)
HStack(spacing: 12) {
Button(action: {
print("Directions button tapped")
}) {
Label("Directions", systemImage: "arrow.triangle.turn.up.right.circle.fill")
.font(.caption)
}
.buttonStyle(.borderedProminent)
Button(action: {
print("Info button tapped")
}) {
Label("Info", systemImage: "info.circle.fill")
.font(.caption)
}
.buttonStyle(.bordered)
}
}
.padding()
.frame(width: 200)
}
}
I've looked at other problems with Map and onTap handlers not getting called, but this is a SwiftUI view inside an AppKit MapKit annotation's callout view.
Any idea of how to handle this?
Maps & Location
RSS for tagLearn how to integrate MapKit and Core Location to unlock the power of location-based features in your app.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
Hello 👋🏼,
We are using MapKit JS to display maps on our application working on two domains .com and .cn. Everything is working for all ours users in the world except for users using Chinese local network.
After investigation, there is an error display in the browser console:
[MapKit] Initialization failed because the authorization token is invalid.
As the tokens are used as they are for the rest of the world, we know that they are valid... 😕
Problem appears on all browsers:
Current versions of MapKit JS
mapkit-typescript @ 5.18.2
https://cdn.apple-mapkit.com/mk/5.49.x/mapkit.js
Do you have any tips, suggestions to help us 🙏 ?
Aurélien.
We are currently experiencing a very interesting issue when accessing the location in the background with CLLocationManager.
The user has given our app the "whenInUse" permission for locations and in most cases the app provides location updates even when it's in the background.
However, when we started to use other navigation apps in the foreground we saw that the func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) method was called with (kCLErrorDomain error 1.).
The user hasn't changed the location permission and we saw that locations were delivered once the user opened the app again.
I don't see anything in the documentation explaining this issue, but I chatted with other developers that confirm that specific behavior.
Am I missing something here?
I have tried to make colored annotations in mapView (shown in the commented sections) but they always appear in black. Any help would be appreciated.
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
let annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: "TempAnnotationView")
annotationView.canShowCallout = true
annotationView.rightCalloutAccessoryView = UIButton(type: .detailDisclosure)
let configuration = UIImage.SymbolConfiguration(pointSize: 10, weight: .thin, scale: .default)
if annotation.title == "Start" {
// let config = UIImage.SymbolConfiguration.preferringMulticolor()
// let image = UIImage(systemName: "flag.fill", withConfiguration: config)
// // palette
// let config2 = UIImage.SymbolConfiguration(paletteColors: [.systemRed, .systemGreen, .systemBlue])
// let image2 = UIImage(systemName: "person.3.sequence.fill", withConfiguration: config2)
// // hierarchical symbols
// let config3 = UIImage.SymbolConfiguration(hierarchicalColor: .systemIndigo)
// let image3 = UIImage(systemName: "square.stack.3d.down.right.fill", withConfiguration: config3)
// // color
// let image4 = UIImage(systemName: "cone.fill")?.withTintColor(.systemRed, renderingMode: .alwaysTemplate)
// annotationView.image = image4
annotationView.image = UIImage(systemName: "poweron", withConfiguration: configuration)
}
return annotationView
}
My app needs to track background location for a period of several hours while the user is using it, and we want to allow the user to switch apps or lock their phone while this is happening. We don't need to track location permanently and because of this, we don't want to request the "Always allow" permission.
The app requests "While in use" permission and it has the "Location updates" background mode enabled. The CLLocationManager has 'allowsBackgroundLocationUpdates' set to true, 'pausesLocationUpdatesAutomatically' false, kCLLocationAccuracyBest, kCLDistanceFilterNone, and .fitness for the activity type (we expect the user to be walking).
The app also initializes a CLBackgroundActivitySession while it is tracking location and invalidates it when done.
When I test this combination on my iPhone, it works fine. I get location tracking in the background for as long as I need it, regardless of what else I do with the phone.
However, my customer says it doesn't work for him. He is using a Wifi-only iPad with an external GPS receiver called "BadElf GPS Pro". He says that the external GPS receiver works fine with other apps on his iPad. With my app, he gets background location tracking only for a short time, and then it stops.
The app does monitor the "locationManagerDidPauseLocationUpdates" callback and posts a local notification if it gets called, but it doesn't get called. I've also confirmed with him that he is not force-quitting the app and the app is not otherwise being terminated by iOS.
Is there something I'm missing?
We are developers of a golf app designed to assist golfers on the course. A key feature of our app is displaying a map of each hole, and we are currently transitioning to using MapKit and camera functionalities for this purpose. However, we are encountering issues with the downloading of map tiles when using the default satellite imagery.
We have tried several approaches to diagnose the issue:
We have tried several things to diagnose the issue:
We implemented the mapViewDidFailLoadingMap delegate method. But it is inconsistent, sometimes triggering offline errors even when map tiles are cached.
We implemented, the mapViewDidFinishRenderingMap method, but it always returns false when offline or you won't get the callback. Which doesn't let us know that rendering tiles has failed.
We would appreciate your guidance on the following specific questions:
Does MapKit provide a way to confirm if a map tile has fully loaded?
Is there a method to detect if a portion of the map hasn't loaded or if a tile request has failed?
Can we determine whether a map tile is cached, and if so, how long it will remain cached, similar to Cache-Control HTTP headers?
Is there a way to trigger the preloading of map tiles when we know the user has a good internet connection?
Please see the sample project for steps to reproduce the issue.
Thank you for any assistance!
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!
Topic:
App & System Services
SubTopic:
Maps & Location
Tags:
Core Location
Maps and Location
Background Tasks
I am able to fetch the location in foreground and background.
I need just confirmation that can we get location apps killed state.
If It's possible then how can I do that.
I'm calling .startUpdatingLocation() from the background to detect user's location but the updates stop shortly after they start.
The issue seem to also be discussed here:
https://developer.apple.com/forums/thread/726945
I wonder if any solution has been found?
This is a critical feature for our app.
I have:
kCLLocationAccuracyBestForNavigation
allowsBackgroundLocationUpdates = true
pausesLocationUpdatesAutomatically = false
Location Updates in background modes
distanceFilter not set or kCLDistanceFilterNone
We are currently testing the implementation of our Location Push Service Extension (LPSE) in both Ad Hoc and Release environments. We have encountered an issue where LPSE notifications, which were previously working correctly, suddenly fail to be delivered on some devices. After a period of several hours, the notifications resume arriving, but the issue remains intermittent. Notably, during these periods of suspected delivery restriction, regular push notifications (e.g., those using apns-push-type: alert) are delivered and displayed without any problem.
[Detailed Situation]
Test Environment and Scope
We are testing LPSE after obtaining the necessary entitlements, in both Ad Hoc and Release environments.
The issue is not observed on all test devices; only certain devices are affected.
Observed Behavior
Under normal circumstances, LPSE notifications are received and the extension is activated; however, on some devices the notifications suddenly stop arriving.
During these periods, even when sending notifications with apns-push-type: location directly via the CloudKit Push Notification Console, no response is observed on the affected devices.
The APNs server (api.push.apple.com) always returns a 200 OK response via HTTP/2, and our server-side logs and configurations (DNS resolution performed on every request, using the same JWT token for 59 minutes per session, communication via HTTP/2 with ALPN Protocol: h2) show no issues.
Other app functionalities (network communication, UI responsiveness, etc.) work normally.
Sending content
When sending notifications from our server to APNs (api.push.apple.com), we use the following configuration (over HTTP/2):
const payload = {
aps: { 'content-available': 1 }
};
const headers = {
':method': 'POST',
':path': /3/device/${apnsToken},
'Authorization': bearer ${jwtToken},
'apns-topic': 'ot.Here.location-query',
'apns-priority': '10',
'apns-push-type': 'location',
'Content-Type': 'application/json'
};
We perform DNS resolution for every request, use the same JWT token for a 59-minute period per session, and communicate via HTTP/2 with ALPN Protocol: h2.
Hypothesis on the Cause
We suspect that due to an implementation issue, silent push notifications (using content-available: 1) were being sent every few minutes concurrently, which may have triggered an APNs delivery restriction (rate limiting).
As a countermeasure, we have completely stopped sending silent pushes and any other background notifications aside from LPSE; however, the issue persists.
Additionally, even after resetting affected devices, the delivery problem continues to occur.
[Questions for Diagnosis]
Given the above situation, is it reasonable to suspect that excessive silent push notifications have triggered an APNs delivery restriction?
Does such a silent push restriction affect LPSE notifications (i.e., those sent with apns-push-type: location)?
Do APNs delivery restrictions persist even after a device has been reset?
Can a high volume of LPSE notifications alone (without silent pushes) also trigger a delivery restriction?
→ This is our primary concern since it poses a significant implementation challenge.
Please let us know if any additional information is required for diagnosis.
The https certificate has expired
I have a Nissan Rogue 2021 and iPhone 14 Pro Max. Carplay was working fine until I decided to update to the new beta program and now my carplay does not seem to want to operate at all. I do the fixes online suggest in rebooting both systems, forgetting entirely and reconnecting. In the process of doing so, I can get the prompts to start with "Allow while unlocked?" But once selecting that I am unable to actually use the Carplay from the phone. It doesn't even give option to switch to it when I attempt to change audio output.
Their support email is broken and our IMDF is stuck at "Occupants Data in Review" step. Thank you
Summary
While parallel testing Core Location on the new iOS 26.1 beta (23B5044i), I observed what I believe to be a regression of the issue described here: https://developer.apple.com/forums/thread/779192
Specifically, user positioning underground subway stations is noticeably inaccurate on the beta, whereas the same scenarios remain accurate on the unupgraded device below.
I work with the MTA (New York City) and work with the OP of that thread. Happy to provide additional testing or details if helpful. Please let me know what else you need.
Test Info
Riding NYCT from Wall St to 34th St Penn Station on the 2 train carrying two iphones
Recording: https://limewire.com/d/dpTWi#pDC3GRYIdE
Expected: Consistent underground positioning comparable to prior releases.
Actual: Degraded/inaccurate underground positioning on iOS 26.1 beta.
Test Devices
Left Screen: iPhone 15 Pro Max - iOS 26.1 beta (23B5044i)
Right Screen: iPhone 11 - iOS 18.6.2 (22G100)
Blue dots show location set by CoreLocation. Red dot on iphone 11 shows the actual location of both devices as I was able to manually place while travelling through a station. Placement through tunnels is not easy to verify and not usually indicated.
Timestamps
Comparison of when train was actually observed in a station vs when 26.1 and 18.6.2 CoreLocation updated to the station
Fulton St
1:48 iOS 26.1 correctly updates (correctly)
2:16 iOS 18.6.2 updates (28sec late)
Park Place
4:12 train arrives
4:15 iOS 18.6.2 updates to ~near Park Place
5:04 iOS 18.6.2 updates to Park Place (correctly)
6:07 iOS 26.1 update to ~near Park Place (over 2 mins late)
Chambers St
6:02 train arrives / iOS 18.6.2 updates (correctly)
6:14 iOS 26.1 updates to ~near Chambers
6:18 iOS 26.1 update to Chambers (correctly)
Franklin St
6:52 train arrives
6:55 iOS 18.6.2 updates (correctly)
x:xx iOS 26.1 does not update
Canal St:
7:16 train arrives
7:18 iOS 18.6.2 updates (correctly)
x:xx iOS 26.1 does not update
Houston St
7:54 train arrives
8:00 iOS 18.6.2 updates (correctly)
x:xx iOS 26.1 does not update
Christopher St
8:37 iOS 26.1 presumably between Houston St and Christopher St
8:40 train arrives / iOS 18.6.2 updates (correctly)
x:xx iOS 26.1 does not update
14 St
9:22 train arrives
9:28 iOS 18.6.2 updates (correctly)
11:01 as train departs station iOS 26.1 updates (1.5 mins late)
Topic:
App & System Services
SubTopic:
Maps & Location
Tags:
Beta
Core Location
Maps and Location
Testing
Hi,
We are using beacon ranging methods to detect beacon in foreground and background in our app. We are using beacon's UUID, major and minor values to create a beacon region and then calling locationManager.startRangingBeacons to range beacons. We listen for beacon updates via the didRangeBeacons delegate method to get beacon data emitted.
However, we've observed some inconsistent behavior:
The beacon region frequently reports exit events even when the device is within close proximity (approximately 1.5 to 2 meters).
There are instances where no beacon updates are received for extended periods (up to 15–20 minutes), despite the beacon being nearby.
Generally, The distance between the device and the beacon is approximately 1.5 - 2 meters.
What could be the reason for this behaviour and how can we avoid it and continuously receive beacon updates when the beacon is near without any delay?
Thanks
Topic:
App & System Services
SubTopic:
Maps & Location
1. The Inquiry
Hello,
I have been implementing a background geofencing feature and, during testing, I found a significant numerical difference in event callback frequency between the older CLCircularRegion API and the newer CLMonitor API (CLMonitor.CircularGeographicCondition), introduced in iOS 17.
My testing was strictly conducted using the "Always Allow" location permission (requestAlwaysAuthorization()). I used both APIs in parallel under identical geofencing conditions and within the same implementation environment. Since a clear difference persists in the data, I suspect this may stem from structural differences in the internal mechanisms of the two APIs rather than an implementation error on my part.
2. Environment and Implementation Details (Proof of Integrity)
I have ensured that my implementation adheres to Apple's guidelines and uses modern Swift concurrency features.
A. Development Environment and Permissions
iOS Version: iOS 18.x and later
Xcode Version: Version 17A400 (Version 26.0.1)
Location Authorization: Always permission obtained.
Background Mode: Location updates is configured correctly in Info.plist.
B. CLMonitor Initialization and Lifecycle
I implemented robust lifecycle management to ensure CLMonitor is stable and persists correctly:
Initialization: I performed CLLocationManager object allocation and related service setup (e.g., CLServiceSession set to always) within the call stack frame of didFinishLaunchingWithOptions.
Monitor Management: I use an Actor-based Singleton pattern to guarantee that only a single CLMonitor instance is used application-wide.
Event Monitoring: Following initialization, I allocated a background Task containing the for try await event in await monitor.events loop. This Task is explicitly managed to persist in the background until the application is terminated, ensuring continuous event listening.
C. Registration Limit Management
I manage both APIs to ensure they never exceed the recommended maximum of 20 simultaneously monitored regions/conditions. My logic removes the oldest item (LRU) when the limit is reached.
The average registration counts during the test period were highly similar:
Component
Average Registered Count
CLCircularRegion count
7.02
CLMonitor.CircularGeographicCondition count
7.04
This confirms that registration count is not the cause of the event frequency difference.
3. Data-Based Observation
The test data (bubble_test_data_for_apple_forum.csv) records the event callbacks for both APIs under identical conditions:
Component
Total Count
Percentage of All Events (%)
CLCircularRegion Delegate Total Calls
617
83.56%
CLMonitor Event Total Fires
122
16.44%
Overall Total Count
739
100%
A. Key Findings
CLCircularRegion Operability: 617 calls confirm that core implementation factors (permissions, background setup, etc.) are functioning correctly.
Disparity in Frequency: Despite running in parallel, the CLMonitor event count (122) is approximately 1/5th the frequency of the CLCircularRegion calls (617).
Efficiency per Registration: CLCircularRegion averaged ~0.86 calls per registered item, while CLMonitor averaged only ~0.17 calls per registered item.
4. Questions for Apple Engineering
Based on the robust implementation and the data presented, I request a review of the following potential differences between the APIs:
Internal Mechanism Differences: Are there structural differences in how CLCircularRegion and CLMonitor.CircularGeographicCondition process and schedule geofencing event callbacks? For instance, do they differ in terms of battery optimization priority, event batching, or internal throttling mechanisms?
CLMonitor Event Ratio: Is the phenomenon where CLMonitor records a significantly lower ratio of events compared to CLCircularRegion an intended behavior, or could this be indicative of a specific environmental factor that affects the newer API differently?
Thank you for your time and assistance.
geofence-test-data.csv
Since iOS 26 the delegate method locationManager(:didVisit:) is no longer invoked reliably while locationManager(:didUpdateLocations:) continues to be called regularly on the same devices. The issue appears to be directly tied to iOS version updates. Visit callbacks worked consistently under iOS 18.x but in some cases stopped being invoked immediately after updating the same device to iOS 26.0. In other cases didVisit worked on iOS 26.0 but stopped after updating to 26.0.1 and similarly from 26.0.1 to 26.1.
The behaviour is inconsistent with no identifiable pattern and affects multiple recent device models.
All required configuration is in place:
– startMonitoringVisits() is called correctly
– location permission is set to “Always”– background mode for location updates is enabled
– allowsBackgroundLocationUpdates is enabled
– restarting the app or the device does not fix the problem
The only workaround that restores visit monitoring is deleting the app and reinstalling the same App Store version which is not a viable solution for end users.
Have other developers experienced the same issue and are there any recommended best practices or technical guidelines to handle missing didVisit callbacks after updating to iOS 26?
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?
This is my first post here. Please guide me, if I need to provide more information to answer this post.
I write a simple application, that monitors GPS position (location). I followed Apple documentation for LiveUpdates: https://developer.apple.com/documentation/corelocation/supporting-live-updates-in-swiftui-and-mac-catalyst-apps
My app can monitor location in foreground, background or it can completely stop monitoring location. Background location, if needed, is switched on when application changes scenePhase to .background. But it is in the foreground, that memory leaks occur (according to Instruments/Leaks. Namely Leaks points to the instruction:
let updates = CLLocationUpdate.liveUpdates()
every time I start location and then stop it, by setting updatesStarted to false.
Leaks claims there are 5x leaks there:
Malloc 32 Bytes 1 0x6000002c1d00 32 Bytes libswiftDispatch.dylib OS_dispatch_queue.init(label:qos:attributes:autoreleaseFrequency:target:)
CLDispatchSilo 1 0x60000269e700 96 Bytes CoreLocation 0x184525c64
Malloc 48 Bytes 1 0x600000c8f2d0 48 Bytes Foundation +[NSString stringWithUTF8String:]
NSMutableSet 1 0x6000002c4240 32 Bytes LocationSupport 0x18baa65d4
dispatch_queue_t (serial) 1 0x600002c69c80 128 Bytes libswiftDispatch.dylib OS_dispatch_queue.init(label:qos:attributes:autoreleaseFrequency:target:)
I tried [weak self] in Task, but it doesn't solve the leaks problem and causes other issues, so I dropped it. Anyway, Apple doesn't use it either.
Just in case this is my function, which has been slightly changed comparing to Apple example, to suit my needs:
func startLocationUpdates() {
Task() {
do {
self.updatesStarted = true
let updates = CLLocationUpdate.liveUpdates()
for try await update in updates {
// End location updates by breaking out of the loop.
if !self.updatesStarted {
self.location = nil
self.mapLocation = nil
self.track.removeAll()
break
}
if let loc = update.location {
let locationCoordinate = loc.coordinate
let location2D = CLLocationCoordinate2D(latitude: locationCoordinate.latitude, longitude: locationCoordinate.longitude)
self.location = location2D
if self.isAnchor {
if #available(iOS 18.0, *) {
if !update.stationary {
self.track.append(location2D)
}
} else {
// Fallback on earlier versions
if !update.isStationary {
self.track.append(location2D)
}
}
}
}
}
} catch {
//
}
return
}
}
Can anyone help me locating these leaks?
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?