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

Posts under Maps & Location subtopic

Post

Replies

Boosts

Views

Activity

MapKit with MKTileOverlay Crashes After a Time
I'm building a weather map that shows the rain on the map. I'm able to retrieve PNG images that are used as tiles to put onto the map. I then reload all the tiles on the map with each timeframe (tile set for every 10 minutes). I'm able to get the map loaded up and I'm able to place the tiles and reload the data for each time slot. I preload all the PNG data needed for the tiles and store that NSData for them in memory so that they are quick for loading and showing on the map. I have timer's set to reload the overlay with the next set of tiles for each time slot. Giving the view of a moving precipitation map over time (just like you'd see on any weather map.) I have 12 time slots (timestamps) showing every 10 minutes for the past 2 hours. I have it showing each in sequence and then repeating. Over time I get a crash with this error as a Thread 1: signal SIGABRT. Failed to acquire drawable, rendering to temporary texture validateRenderPassDescriptor:782: failed assertion `RenderPass Descriptor Validation MTLRenderPassAttachmentDescriptor MTLStoreActionMultisampleResolve store action at attachment 0 requires resolve texture ' validateRenderPassDescriptor:782: failed assertion `RenderPass Descriptor Validation MTLRenderPassAttachmentDescriptor MTLStoreActionMultisampleResolve store action at attachment 0 requires resolve texture ' Through some searching I've discovered that this seems to be console output from Metal. I assume Metal is used for MapKit to render the overlay tiles? I'm using the same custom overlay where I set the timestamp on it and then tell it to reload. I also reuse the same MKOverlayRenderer as shown here... - (MKOverlayRenderer*)mapView:(MKMapView*)mapView rendererForOverlay:(id<MKOverlay>)overlay { if ([overlay isKindOfClass:[MKTileOverlay class]]) { if (!self.rainRenderer) { self.rainRenderer = [[MKTileOverlayRenderer alloc] initWithTileOverlay:overlay]; self.rainRenderer.alpha = 0.5; } return self.rainRenderer; } return nil; } And here's the function that reloads the overlay... - (void) updateRainFrame { self.currentFrameIndex = (self.currentFrameIndex + 1) % self.timestamps.count; if ((self.currentFrameIndex >= 0) && (self.timestamps.count > self.currentFrameIndex)) { NSLog (@"self.currentFrameIndex = %lu", self.currentFrameIndex); NSString *timestamp = self.timestamps[self.currentFrameIndex]; [self.overlay setTimestamp:timestamp]; [self.rainRenderer reloadData]; } } The time it takes to crash seems arbitrary. Sometimes it's very quick. Less than a minute. But usually it's several minutes. 10 or 20 minutes or more. Feels like some sort of race condition that's occurring. Perhaps ARC is not able to release the images for the tiles quick enough for each overlay reload? That's a wild guess but I think it's something more deeper in Metal as I feel I would see other errors related to memory availability. Some of my searches point to something about MSAA needing to be turned off in Metal to resolve this. However I have no idea how I would do that through MapKit. Any suggestions? Let me know if there is somehow a way to capture more from the crash to give more insight.
2
0
136
Jun ’25
How to Handle Periodic Background Location Reminders for an MDM-Managed Safety App?
Hello everyone, We've developed a safety application for schools that runs on supervised, MDM-managed iOS devices. The app requires "Location Always" to maintain a persistent background state for its core functionality. The Challenge: Our primary issue is with the periodic background location reminder prompts that iOS automatically presents to the user (e.g., "[App Name] has used your location X times in the past 3 days..."). A screenshot of the exact prompt is attached. While we educate users on the importance of selecting "Always Allow," these recurring prompts make it very easy for a student to downgrade the permission at a later date, which disables the app's safety features. This makes the solution unreliable in a school environment. Our Question: Since these are supervised devices managed by an educational institution, we are looking for a way to manage this behavior. Is there any Info.plist key, entitlement, or API available to developers to influence or suppress these recurring location reminders for our app? From an MDM perspective, is there a known payload or declarative management configuration that can prevent these specific prompts from appearing for a designated app? We understand these prompts are a key privacy feature. Our question is whether there are any provisions for managed, special-purpose environments like a school, where the app's function is considered essential and pre-approved by the device administrator (the school). We are looking for a way to provide a "set it and forget it" configuration for the school, but these reminders currently prevent that. Any architectural advice or insights would be greatly appreciated. Thank you.
2
0
117
Jul ’25
Bluetooth permissions Query
Hi Team, when our customers turn on bluetooth connectivity whether Apple creates a profile of the user or their locations and if it is used for any other purpose. Could you please clarify this? we are getting the below message in the Bluetooth permissions popup below the map "Information from Bluetooth devices can be used to determine your location and create a profile of you." What is this profile? and what is the purpose of creating it while the user uses Bluetooth in ios app.
2
0
94
Aug ’25
MapKit JS Look Around not pointing camera towards the lat/lng entered
We are using MapKit JS Look Around and initializing it like this: window.lookAround = new mapkit.LookAround( document.getElementById('container'), new mapkit.Coordinate(listingLocation[1], listingLocation[0]), {openDialog: false}) ; This results in a Look Around scene being displayed correctly but the camera heading is not pointing towards the lat/lng that is passed to initialization. The example lat/lng that we're using is: lat=30.004195, lng=-95.59973 This lat/lng corresponds to the address: 11943 Laurel Meadow Dr, Tomball, TX 77377. The camera is pointing to the other side of the street to house number 11946. If you look for that address in Apple Maps the Look Around points to the correct house. Is there a way to either specify the heading so that Look Around points in the correct heading? Sample link: https://s.hartech.io/zFP2KnsCbsP
2
0
124
Sep ’25
SwiftUI issue with onTap using Map using IOS 26
I have a sample that stop working on IOS 26, using the latest XCode and IOS sdk, the onTapGesture event is no longer happening. Maybe this is no longer the way to drop pins on the map. Also not working on the iPhone 17 sim or iPhone 16 max pro device upgrading to IOS 26 Thanks, any help Sample: import SwiftUI import MapKit import CoreLocation import Foundation struct Pin: Identifiable { let id = UUID() let coordinate: CLLocationCoordinate2D } struct ContentTestPinDropView: View { @State private var pins: [Pin] = [] var body: some View { MapReader { reader in Map(selection: .constant(nil)) { ForEach(pins) { pin in Marker("Pin", coordinate: pin.coordinate) } } .onTapGesture { screenPoint in if let coordinate = reader.convert(screenPoint, from: .local) { pins.append(Pin(coordinate: coordinate)) } } } } }
2
0
204
Oct ’25
CLLocation.sourceInformation.isSimulatedBySoftware not detecting third-party location spoofing tools
Summary CLLocationSourceInformation.isSimulatedBySoftware (iOS 15+) fails to detect location spoofing when using third-party tools like LocaChange, despite Apple's documentation stating it should detect simulated locations. Environment iOS 18.0 (tested and confirmed) Physical device with Developer Mode enabled Third-party location spoofing tools (e.g., LocaChange etc.) Expected Behavior According to Apple's documentation, isSimulatedBySoftware should return true when: "if the system generated the location using on-device software simulation. " Actual Behavior Tested on iOS 18.0: When using LocaChange sourceInformation.isSimulatedBySoftware returns false This occurs even though the location is clearly being simulated. Steps to Reproduce Enable Developer Mode on iOS 18 device Connect device to Mac via USB Use LocaChange to spoof location to a different city/country In your app, request location updates and check CLLocation.sourceInformation?.isSimulatedBySoftware Observe that it returns false or sourceInformation is nil Compare with direct Xcode location simulation (Debug → Simulate Location) which correctly returns true
2
0
172
Oct ’25
OS Location via Bluetooth GPS receiver
Hello, We are a software and hardware development company for the forestry and environmental sectors. We have been based in Quebec (Canada) for over 30 years now. Our Canadian market covers Quebec, Ontario, and the Maritime provinces in the east. We are currently expanding across Canada and into the northern United States. We are on Android platforms with several map and data entry applications. To ensure the success of our expansion, we aim to become part of the Apple family, which is why we are contacting you today. We have developed our own GNSS receiver to increase the location accuracy of our users. This device is called GSFGPS. It uses Bluetooth BLE to communicate with mobile devices and a high-precision GPS that transmits its position using the NMEA protocol. We would like this device to be compatible with an iPhone/iPad. We have developed a mock location application in MAUI (multi-platform). Based on our interpretation of your documentation, we understand that the concept of mock location does not exist at Apple. How can we ensure that our Bluetooth GNSS device is compatible with your iPhone/iPad devices and that they can use the position of the Bluetooth device rather than the internal GPS of your devices? We are a reseller for Juniper Systems, and we know that they have an app on the App Store that has the same features as our product. https://junipersys.com/index.php/support/article/14709 We look forward to your follow-up and recommendations.
2
0
183
Oct ’25
iOS 26: Maps share sheet no longer provides com.apple.mapkit.map-item and only shares short maps.apple/p/... URLs (how to get coordinates?)
Since iOS 26, the Apple Maps share sheet no longer provides a com.apple.mapkit.map-item attachment when sharing a location to my Share Extension. Additionally, on real devices the shared URL is now a short link (https://maps.apple/p/...), which does not contain coordinates. On the simulator, the URL still includes coordinates (as in previous iOS versions). I'm trying to find the official or recommended way to extract coordinates from these new short URLs. Environment: Devices: iPhone (real device) on iOS 26.0 / 26.0.1 Simulator: iOS 26.0 / 26.0.1 simulator (behaves like iOS 18 — see below) App: Share Extension invoked from Apple Maps -> Share -> my app Xcode: 26.0.1 Steps to Reproduce Open Apple Maps on iOS 26 (real device). Pick a POI (store/restaurant). Share -> choose my share extension. iOS 18 and earlier (lldb) po extensionContext?.inputItems ▿ Optional<Array<Any>> ▿ some : 1 element - 0 : <NSExtensionItem: 0x60000000c5d0> - userInfo: { NSExtensionItemAttachmentsKey = ( "<NSItemProvider: 0x600002930d20> {types = (\"public.plain-text\")}", "<NSItemProvider: 0x600002930c40> {types = (\"com.apple.mapkit.map-item\")}", "<NSItemProvider: 0x600002930bd0> {types = (\"public.url\")}" ); } Typical URL: https://maps.apple.com/place?address=Apple%20Inc.,%201%20Apple%20Park%20Way,%20Cupertino,%20CA%2095014,%20United%20States&coordinate=37.334859,-122.009040&name=Apple%20Park&place-id=I7C250D2CDCB364A&map=explore iOS 26 (lldb) po extensionContext?.inputItems ▿ 1 element - 0 : <NSExtensionItem: 0x6000000058d0> - userInfo: { NSExtensionItemAttachmentsKey = ( "<NSItemProvider: 0x600002900b60> {types = (\"public.url\")}", "<NSItemProvider: 0x600002900fc0> {types = (\"public.plain-text\")}" ); } URL looks like: https://maps.apple/p/U8rE9v8n8iVZjr On simulator iOS 26 same missing map-item provider - but the URL is still long and contains coordinates, like this: https://maps.apple.com/place?coordinate=37.334859,-122.009040&name=Apple%20Park&.. Issue The short URLs (maps.apple/p/...) cannot be resolved directly - following redirects ends with: https://maps.apple.com/unsupported The only way I've found to get coordinates is to intercept intermediate redirects - one of them contains the expanded URL with coordinate=.... Example of my current workaround: final class RedirectSniffer: NSObject, URLSessionTaskDelegate { private(set) var redirects: [URL] = [] func urlSession(_ session: URLSession, task: URLSessionTask, willPerformHTTPRedirection response: HTTPURLResponse, newRequest request: URLRequest) async -> URLRequest? { if let url = request.url { redirects.append(url) } return request } } Then I look through redirects to find a URL containing "coordinate=". This works, but feels unreliable and undocumented. Questions Was the removal of com.apple.mapkit.map-item from the Maps share payload intentional in iOS 26? If yes, is there a new attachment type or API to obtain an MKMapItem? What’s the official or supported way to resolve https://maps.apple/p/... to coordinates? Is there any MapKit API or documented URL scheme for this? Is intercepting redirect chains the only option for now? Why does the iOS 26 simulator still return coordinate URLs, while real devices don't?
2
0
285
Oct ’25
MapKit detailAccessoryView buttons not working on macOS Tahoe
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?
2
0
146
Nov ’25
Direction data not available with U2 chip (iPhone 15 Pro and iPhone 16 Pro) when using Murata SR040/SR150 accessory
Hello, I am developing with the Nearby Interaction framework using third-party UWB accessories (Murata SR040/SR150). I observed a difference between U1-based and U2-based iPhones: iPhone 12 Pro (U1 chip) NINearbyObject.direction returns valid 3D vector (x, y, z). Distance and direction both work as expected. iPhone 15 Pro and iPhone 16 Pro (U2 chip) NINearbyObject.direction is always nil. Only distance is returned (around 0.35–0.40 m in my test). Effectively behaves as "distance-only mode". Environment: Hardware: iPhone 12 Pro, iPhone 15 Pro iOS version: 18.5 Accessory: Murata UWB SR040 / SR150 App: Using NINearbyAccessoryConfiguration with BLE-based discovery Info.plist includes NSNearbyInteractionUsageDescription Camera assistance was tested both ON and OFF Expectation: I expected the U2 chip to behave consistently with U1, i.e. provide direction vectors when possible. Instead, on iPhone 15 Pro, direction is always unavailable (nil) while distance is returned correctly. Questions: Is this an intentional limitation for U2 chip + third-party accessories? Is there a new requirement (e.g. certification, firmware update, capability flags) to enable direction on U2 devices? Could this be related to NIDeviceCapability or the new Extended Distance Measurement (EDM) mode in U2? Thanks in advance for any clarification.
2
3
236
3w
DataCloneError in MapKit JS Worker when posting non-detachable ArrayBuffers (Chrome ≥120)
Since integrating MapKit JS, we’ve begun receiving production error reports with the following message: Uncaught DataCloneError: Failed to execute 'postMessage' on 'DedicatedWorkerGlobalScope': ArrayBuffer is not detachable and could not be cloned. It appears that MapKit JS’s internal worker occasionally calls postMessage() with an ArrayBuffer that cannot be detached under Chrome 120+. This causes the structured clone to fail and the error surfaces uncaught from within the worker. MapKit JS Version: 5.79.109 Browser: Chrome 120.0+ OS: Windows 10 Is this a known issue with MapKit JS? If so, are there recommended workarounds or planned fixes?
2
0
168
3w
Stopping and Resuming Background Location Activity with CLLocationUpdates and CLBackgroundActivitySession
Hello, This is my first post in the forums, and I'm still learning my way with iOS Development and Swift. My apologies if the formatting is not correct, or If I'm making any mistakes. I'm currently trying to implement an iOS App where the device needs to share the location with my server via an API call. The use case is as follows: the server expects location updates to determine if a device is inside/outside a geofence. If the device is stationary, no locations need to be sent. If the device begins moving, regardless of whether the app is in foreground, background, or terminated, the app should resume posting locations to the server. I've decided to use the CLLocationUpdate.liveUpdates() stream, together with CLBackgroundActivitySession(). However, I have not been able to achieve the behavior successfully. My app either maintains the blue CLActivitySession indicator active, regardless of whether the phone is stationary or not, or kills the Indicator (and the background capability) and does not restore it when moving again. Below I've attached my latest code snippet (the indicator disappears and does not come back). // This method is called in the didFinishLaunchingWithOptions func startLocationUpdates(precise: Bool) { // Show the location permission pop up requestAuthorization() // Stop any previous sessions stopLocationUpdates() Task { do { // If we have the right authorization, we will launch the updates in the background // using CLBackgroundActivitySession if self.manager.authorizationStatus == .authorizedAlways { self.backgroundActivity = true } else { self.backgroundActivity = false self.backgroundSession?.invalidate() } // We will start collecting live location updates for try await update in CLLocationUpdate.liveUpdates() { // Handle deprecation let stationary = if #available(iOS 18.0, *) { update.stationary } else { update.isStationary } // If the update is identified as stationary, we will skip this update // and turn off background location updates if stationary { self.backgroundSession?.invalidate() continue } // if background activity is enabled, we restore the Background Activity Session if backgroundActivity == true { self.backgroundSession = CLBackgroundActivitySession() } guard let location = update.location else { continue } // Do POST with location to server } } catch { print("Could not start location updates") } } } I'm not sure why the code does not work as expected, and I believe I may be misunderstanding how the libraries Work. My understanding is that the liveUpdates stream is capable of emitting values, even if the app has gone to the background/terminated, thus why I'm trying to stop/resume the Background Activity using the "stationary" or "isStationary" attribute coming from the update. Is the behavior I'm trying to achieve possible? If so, I'm I using the right libraries for it? Is my implementation correct? And If not, what would be the recommended approach? Regards
2
1
88
2w
Reverse geocoding rate limit of MKReverseGeocodingRequest compared to CLGeocoder
The documentation for CLGeocoder states Geocoding requests are rate-limited for each app, so making too many requests in a short period of time may cause some of the requests to fail. (When the maximum rate is exceeded, the geocoder returns an error object with the CLError.Code.network error to the associated completion handler.) And it provides helpful guidance on how and when to submit geocoding requests. The documentation for MKReverseGeocodingRequest does not mention requests are rate-limited. Does this mean it is not rate-limited? If it is rate-limited, is it similar to CLGeocoder, what is its behavior? It is important to understand behavior of the API in order to understand impact on my app’s use case and how users will be affected should I change the implementation. Thanks!
2
1
220
1w
How can you determine if the map tiles in MapKit have successfully loaded?
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!
3
0
454
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
658
Feb ’25
Background location tracking on iPad fails
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?
3
0
626
Feb ’25