Two separate app projects need maps or navigation:
Offline map: offline vector map of small city needed within the app (avoiding any online connection after the app's install). Apple Maps requires map tile download after installation. What is an alternative solution?
Navigation: An app with a list of locations where we don't want to build-in maps or navigation. Would it be possible to allow the user to click on a location, app copies GPS coordinates, and opens default iOS navigation app and navigates from there instead?
Working in Xcode with Swift and SwiftUI.
Maps and Location
RSS for tagBuild maps and location awareness capabilities into your apps.
Posts under Maps and Location tag
85 Posts
Sort by:
Post
Replies
Boosts
Views
Activity
My macOS application is trying to fetch location, but everytime LocationManager responds with locationUnknown. Application is granted with permission to access location. Issue is seen in only one device with OSVersion: 14.2.1(23C71), chipset: Apple M1 pro. Other devices with same OS don't have this issue.
My application is a background agent, means it has given UIElement in the plist.
Issue persists even after restarting device, re-installing application, re-applying location permission. But Google Chrome shows correct location when using Openstreet Map or Google Maps.
Is there any troubleshoot/alternative methods here? Any idea why it occurs?
Code:
if CLLocationManager.locationServicesEnabled() {
if #available(OSX 10.14, *) {
self.locationManager.requestLocation()
} else {
// Fallback on earlier versions
self.locationManager.startUpdatingLocation()
}
}
I need to get location in certain intervals. So After LocationManager updates I stop location with locationManager.stopUpdatingLocation() and request again after the interval.
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
}
CLMonitor WWDC video, it says the same name can be reused await CLMonitor("greeting") but the production iOS 17 API actually crashes. Is this the correct behaviour? (See screenshot 1)
for try await events in monitor.events should work in from the WWDC video, but the production iOS 17 API does not work and need to insert await after in keyword. Also, never received any events from the monitor (See screenshot 2)
WWDC Video: https://developer.apple.com/wwdc23/10147
We are implementing indoor positioning and proximity sensing in our iOS app using iBeacons. We have placed multiple beacons to detect the proximity of one point of interest(POI). We are using the startRangingBeacons method in the CLLocationManager class and implementing corresponding delegates to receive the ranging information. With all required foreground and background permissions granted, when a user walks from one POI to another, beacon ranging is working as expected and we are continuously receiving the sightings in the app.
We have observed that, if user stops walking for a few minutes at a POI and then device automatically pauses the scan. Hence, we will not receive any beacon signals. When there is a movement, it performs beacon ranging again for a minute or so, then stops again for longer time even when user is walking. The interval between the pausing and resuming the service is not a constant. We have also observed that sometimes it takes more than 15 minutes to resume the service once the system pauses the ranging automatically. Is it an expected behavior? How long does it usually take for beacon ranging services to resume after the user starts moving? Is there any way we can reduce this delay between the pause and resume of ranging beacons?
Appreciate your support
Hi All,
I need user continues location event if app in background and terminated (Not-running) mode
below is the code I'm using to get the location but still I'm not get the location continuously
import BackgroundTasks
import UIKit
class AppDelegate: UIResponder, UIApplicationDelegate {
var significatLocationManager: CLLocationManager?
func startSignificationLocation() {
self.significatLocationManager = CLLocationManager()
self.significatLocationManager?.delegate = self
self.significatLocationManager?.activityType = .fitness
self.significatLocationManager?.distanceFilter = 10
self.significatLocationManager?.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
self.significatLocationManager?.allowsBackgroundLocationUpdates = true
self.significatLocationManager?.pausesLocationUpdatesAutomatically = false
self.significatLocationManager?.startUpdatingLocation()
self.significatLocationManager?.startMonitoringSignificantLocationChanges()
self.significatLocationManager?.requestAlwaysAuthorization()
}
func stopAllRegionMonitoring(locationManager:CLLocationManager?){
for delRegion in (locationManager?.monitoredRegions ?? []){locationManager?.stopMonitoring(for: delRegion)}
}
}
extension AppDelegate: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
self.myLocation = locations.last
//call update My Location API
if (self.myLocation?.horizontalAccuracy ?? 0.0) <= (self.liveLocationTrackingRegionRadius + 15.0 ){
self.createRegion(location: self.myLocation)
} else {
manager.stopUpdatingLocation()
manager.startUpdatingLocation()
}
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {}
func locationManagerDidPauseLocationUpdates(_ manager: CLLocationManager) {
manager.startUpdatingLocation()
}
func locationManagerDidResumeLocationUpdates(_ manager: CLLocationManager) {
manager.startUpdatingLocation()
}
}
extension AppDelegate {
func createRegion(location:CLLocation?, type:LocationRegionMonitoringTyep = .LiveLocationTracking) {
if self.significatLocationManager == nil {
self.startSignificationLocation()
}
guard let location = location else { return }
guard CLLocationManager.isMonitoringAvailable(for: CLCircularRegion.self) else{ return }
var identifier:String = "Live_Location_Tracking-" + "\(location.coordinate.latitude)" + "-" + "\(location.coordinate.longitude)"
if (self.significatLocationManager?.monitoredRegions.count ?? 0) > 10 {
self.stopAllRegionMonitoring(locationManager: self.significatLocationManager)
}
var region : CLCircularRegion?
region = CLCircularRegion(center: CLLocationCoordinate2D(latitude: location.coordinate.latitude,longitude: location.coordinate.longitude),radius: 10.0 ,identifier: identifier)
region?.notifyOnExit = true
self.significatLocationManager?.startUpdatingLocation()
if let reg = region {
self.significatLocationManager?.startMonitoring(for: reg)
}
}
func stopAllRegionMonitoring(locationManager:CLLocationManager?){
let WOMRequestId:String? = UserDefaultManager.shared.womEmergencyDetails?.data?.request?.id
for delRegion in (locationManager?.monitoredRegions ?? []){
if let reqId = WOMRequestId {
if delRegion.identifier.contains(reqId) {
locationManager?.stopMonitoring(for: delRegion)
}
} else {
locationManager?.stopMonitoring(for: delRegion)
}
}
}
func locationManager(_ manager: CLLocationManager, didEnterRegion region: CLRegion) {
if region.identifier.contains(AppConstants.WatchOverMe) {
AppDelegate.shared?.isWOMReachDestination(location: manager.location, region: region)
} }
func locationManager(_ manager: CLLocationManager, didExitRegion region: CLRegion) {
self.myLocation = manager.location
manager.stopMonitoring(for: region)
self.significatLocationManager?.stopMonitoring(for: region)
manager.startUpdatingLocation()
self.significatLocationManager?.startUpdatingLocation()
self.createRegion(location: self.myLocation)
//update M yLocation API
if region.identifier.contains( AppConstants.WatchOverMe ) {
TabBarController.isWOMReachDestinationAlertShown = false
}
}
func locationManager(_ manager: CLLocationManager, monitoringDidFailFor region: CLRegion?, withError error: Error) {
self.myLocation = manager.location
self.createRegion(location: self.myLocation)
}
}
extension AppDelegate {
func applicationDidEnterBackground(_ application: UIApplication) {
self.scheduleBackgroundTask()
}
func application(_ application: UIApplication, performFetchWithCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
completionHandler(.newData)
}
func registerBGTask(){
BGTaskScheduler.shared.register(forTaskWithIdentifier: self.getBGTaskIdentifier(), using: nil) { task in
self.handleBackgroundTask(task: task as! BGAppRefreshTask)
}
}
func handleBackgroundTask(task: BGAppRefreshTask) {
task.setTaskCompleted(success: true)
}
func scheduleBackgroundTask() {
let request = BGAppRefreshTaskRequest(identifier: self.getBGTaskIdentifier() )
request.earliestBeginDate = Date(timeIntervalSinceNow: 10) // 30 second
do {
try BGTaskScheduler.shared.submit(request)
} catch {
print("Unable to schedule background task: (error)")
}
}
func getBGTaskIdentifier()->String {
let bundleId:String = AppInfoManager.shared.bundleId + ".locationBackgroundTask"
return bundleId
}
func startLocationTrackingTimer() {
self.stopLocationTrackingTimer()
self.locationTrackingTimer = Timer.scheduledTimer(timeInterval: 1.0,target: self,
selector: #selector(self.updateUserLocation),userInfo: nil,repeats: true)
RunLoop.current.add(self.locationTrackingTimer!, forMode: .common)
}
func stopLocationTrackingTimer() {
self.locationTrackingTimer?.invalidate()
self.locationTrackingTimer = nil
}
@objc func updateUserLocation() {
if self.isSocketActive {
self.updateMyLocationAPI(fromRoam: false)
} else {
self.updateUserCurrentLocation()
}
}
}
I am using CLLocationUpdate.liveUpdates() and CLBackgroundActivitySession to receive background location updates. My app has "Always" authorization, but I can not get rid of the top left "Blue bar" in any way except for by manually closing the app (swipe up in multi-app preview view). I have tried setting CLLocationManager.showsBackgroundLocationIndicator = false but it does not make any difference.
How can I get rid of the blue bar in the top left corner?
My project started from this WWDC23 sample code
Has "always" location authorisation through CLLocationManager.requestAlwaysAuthorization()
Has UIBackgroundModes - location set in Info.plist
Tested multiple days with a real iPhone 14, iOS 17.2 (although an iPhone SE gen2 iOS 17.2 seems to loose the blue bar after a while)
In m1 MACs run
sudo arch -x86_64 pod install --allow-root
to resolve this issue.
I figured out how to use a Mapkit offline in swift and make the map usable offline . Would a project with a Mapkit still be accepted in the contest?
Another question!
Are essays required this year? I don't see it in the requirements.
Hello,
I'm looking for an end-to-end example project that shows a correct implementation for the new iBeacon CoreLocation APIs in iOS 17.0 (CLMonitor, etc.). Ideally the example would cover background waking as that is the area in which I am facing the largest challenges.
Perhaps there's an Open Source project or an official Apple example?
Thanks for pointing me in the right direction.
Jeremy
How would one update the position of a SwiftUI Map without impacting the zoom (or distance from a MapCamera point of view). So want:
a) map position being updated by incoming GPS co-ordinates
b) user may then on the Map zoom in/out
c) on subsequent GPS position changes I want to to keep the zoom/distance changes from the User and not reset these
From the code below the the issue seems to be when getting the current "distance" (i.e. mapCamPost.camera?distance) that this value seems to go to "nil" after the User zooms in the map.
struct GCMap: View {
@StateObject var locationMgr = GcFlightState()
@State private var mapCamPos: MapCameraPosition = .automatic
var body: some View {
ZStack {
Map(position: $mapCamPos) {
Annotation("UserLocation", coordinate: self.locationMgr.location.coordinate) {
Image(systemName: "airplane.circle").rotationEffect(.degrees(270))
}
}
.onMapCameraChange() {
print("onMapCameraChange \(mapCamPos.camera?.distance)")
}
.onReceive(locationMgr.$location) { location in
mapCamPos = .camera(MapCamera(
centerCoordinate: location.coordinate,
distance: mapCamPos.camera?.distance ?? 1000, // <<===
heading: location.course
))
}
}
}
}
Anyone able to see how to use the new SwiftUI Map and WWDC @Observable concept to dynamically update my SwiftUI Map position and rotation based on the dynamic changes it picks up from my @Observable object.
Note the updates are coming through as the Text labels show this. But how to get the Map position referencing the same values and updating them? The "onAppear" approach doesn't seem to work.
import SwiftUI
import MapKit
@Observable
final class NewLocationManager : NSObject, CLLocationManagerDelegate {
var location: CLLocation? = nil
var direction: CLLocationDirection = 0
private let locationManager = CLLocationManager()
func startCurrentLocationUpdates() async throws {
if locationManager.authorizationStatus == .notDetermined {
locationManager.requestWhenInUseAuthorization()
}
for try await locationUpdate in CLLocationUpdate.liveUpdates() {
guard let location = locationUpdate.location else { return }
print("NewLocationManager: \(location.coordinate.latitude), \(location.coordinate.longitude)")
self.location = location
self.direction = self.direction + 1
}
}
}
struct ContentView: View {
var locationMgr = NewLocationManager()
@State private var mapCamPos: MapCameraPosition = .automatic
private let bigBen = CLLocationCoordinate2D(latitude: 51.500685, longitude: -0.124570)
var body: some View {
ZStack {
Map(position: $mapCamPos)
.onAppear { // Does NOT work - how to get position/direction updates working to Map (map should be moving/rotating)
mapCamPos = .camera(MapCamera(
centerCoordinate: self.locationMgr.location?.coordinate ?? bigBen,
distance: 800,
heading: self.locationMgr.direction
))
}
VStack (alignment: .leading) {
Text("Location from observable: \(locationMgr.location?.description ?? "NIL")") // This works (they get updates regularly)
Text("Direction from observable: \(locationMgr.direction)") // This works (they get updates regularly)
Spacer()
}
}
.task {
try? await locationMgr.startCurrentLocationUpdates()
}
}
}
#Preview {
ContentView()
}
Tag: wwdc2023-10043
Case-ID: 4977264
I am writing to inquire about the status of my location push service extension entitlement, which I submitted a consent form for on November 16, 2023., It has been 50 days with no response from Apple since I submitted, Can anyone help regarding the entitlement and why Apple takes time to approve OR is there any specific reason to deny entitlement?
Thanks in advance.
Trying to use new Swift @Observable to monitor GPS position within SwiftUI content view. But how do I tie the latest locations to the SwiftUI Map's mapCameraPosition?
Well ideally the answer could cover:
How to fix this error - So get map tracking along with the User Position, but also
How to include facility to turn on/off the map moving to track the user position (which I'll need to do next). So could be tracking, then disable, move map around and have a look at things, then click button to start syncing the mapcameraposition to the GPS location again
Refer to error I'm embedded in the code below.
import SwiftUI
import MapKit
@Observable
final class NewLocationManager : NSObject, CLLocationManagerDelegate {
var location: CLLocation? = nil
private let locationManager = CLLocationManager()
func startCurrentLocationUpdates() async throws {
if locationManager.authorizationStatus == .notDetermined {
locationManager.requestWhenInUseAuthorization()
}
for try await locationUpdate in CLLocationUpdate.liveUpdates() {
guard let location = locationUpdate.location else { return }
self.location = location
}
}
}
struct ContentView: View {
var newlocationManager = NewLocationManager()
@State private var cameraPosition: MapCameraPosition = .region(MKCoordinateRegion(
center: newlocationManager.location?.coordinate ?? <#default value#>,
span: MKCoordinateSpan(latitudeDelta: 0.25, longitudeDelta: 0.25)
))
// GET ERROR: Cannot use instance member 'newlocationManager' within property initializer; property initializers run before 'self' is available
var body: some View {
ZStack {
Map(position: $cameraPosition)
Text("New location manager: \(newlocationManager.location?.description ?? "NIL" )") // works
}
.task {
try? await newlocationManager.startCurrentLocationUpdates()
}
}
}
#Preview {
ContentView()
}
Regardless of how much information is provided to the Maps searchAutoComplete API, the response field structuredAddress is always null. This means I have to call the completionUrl afterwards to get a structured address. This consumes our quota and causes unnecessary Maps traffic.
Example request, autocompleting "450 Post St, San Francisco":
https://maps-api.apple.com/v1/searchAutocomplete?
q=450%20Post%20St%2C%20San%20Francisco
&resultTypeFilter=Address
&limitToCountries=US
&lang=en-US
responds 2 results with the actual address found, but each having only these fields:
- completionUrl
- displayLines
- location
Example:
{
"results": [
{
"completionUrl": "/v1/search?q=450%20Post%20St%20San%20Francisco%2C%20CA%2C%20United%20States&metadata=Ch8KCzQ1MCBQb3N0IFN0EgQIABADEgQIBBAEEgQICRACEjQKIFNhbiBGcmFuY2lzY28sIENBLCBVbml0ZWQgU3RhdGVzEgQIGhACEgQIABADEgQIBBAJGAIyRgoSCQAAAEDg5EJAEQAAAOA9ml7AEM6h0aK1wfKqciA5KQAAAAAAAHlAgvEEAzQ1MIjxBDGa8QQCVVOg8QQAsvEEALrxBABiHAoaNDUwIFBvc3QgU3QsIFNhbiBGcmFuY2lzY2%2BC8QQaNDUwIFBvc3QgU3QsIFNhbiBGcmFuY2lzY2%2BI8QQA2vEEFgkAAABAEf3IQBkAAAAAAAAAACABKAPq8QQAkPIEAQ%3D%3D",
"displayLines": [
"450 Post St",
"San Francisco, CA, United States"
],
"location": {
"latitude": 37.78809356689453,
"longitude": -122.41002655029297
}
},
{
"completionUrl": "/v1/search?q=450%20Post%20St%20Napa%2C%20CA%2C%20United%20States&metadata=****",
"displayLines": [
"450 Post St",
"Napa, CA, United States"
],
"location": {
"latitude": 38.30093002319336,
"longitude": -122.27799224853516
}
}
]
}
Anyone figured this out? Seems buggy to me.
Question: Does anyone have experience or documentation on how to get an App Clip to show on Apple Maps for a location?
What I've tried: I have tried to associate my App Clip with an Apple Maps location. We are working with a physical restaurant that has an Apple Maps location, our full app is listed there but not the App Clip.
I've gone through the steps of setting up the Advanced App Clip Experience and giving it the location we want it associated with, and have gone through Apple Business Connect and done all the setup there to get the full app to show with the location, but the app clip still does not show.
I've contacted Apple Support and they gave me the criteria of "The App Clip is hosted within the app" and "The app is associated to the same physical location". When asking for clarification with the first criteria they said they could help and closed the chat.
I have recently been approved for the location push service extension. I do not have as much experience working directly in swift. I am trying to Implement so that when this Location Push Notification is received by the device it responds to the server with the current location. I have the proper APNS set up and have already been approved. Is there a step by step guide to help implement this feature.
I'm working on an in-house iOS app designed to help users accurately track their routes during trips. Currently, I've implemented a method to track users when the app is open in the background. However, I'm facing challenges, as the tracking stops when the device is locked for more than 10 minutes.
I'm looking for a solution to continuously track a user's geolocation, even if the app is closed or not in use. Specifically, I want to ensure uninterrupted tracking, especially when the device is locked.
Here are some key points:
Current Method: I'm currently using the Core Location method and a combination of background tasks and a repeating timer to fetch the user's location and update a log for geolocation tracking when the app is open in the background.
Issues Faced: The tracking stops when the device is locked for more than 10 minutes. This limitation impacts the accuracy of the route tracking during longer trips.
Objective: My goal is to achieve continuous geolocation tracking, even when the app is closed or not actively used, to provide users with a seamless and accurate record of their routes.
Platform: The app is developed for iOS using the .net maui platform, and I'm seeking solutions or suggestions that are compatible with the iOS .net maui environment.
If anyone has experience or insights into achieving continuous geolocation tracking on iOS, especially when the app is not in use or the device is locked, I would greatly appreciate the assistance.
I'am developing an iOS widget for my weather app, where the user can set the widget to "My location". This means the widget needs to be refreshed on location changes. Since a widget can't run a location manager in the background, apple tech support wrote that you have to setup a location manager in the main app and share the updated location data over App groups to the widget. This part works fine. I also managed to setup a location manager running in the background, but it uses too much battery and shows always the location indicator on top (blue bar) if the app is running, but I don't need this since its not a navigation app or something similar. How to configure a lightweight location manager running in the background?
class WidgetLocationManager: NSObject, CLLocationManagerDelegate {
static let shared: WidgetLocationManager = WidgetLocationManager()
let manager = CLLocationManager()
override init() {
super.init()
manager.delegate = self
manager.desiredAccuracy = kCLLocationAccuracyKilometer
manager.distanceFilter = 1000
manager.allowsBackgroundLocationUpdates = true
manager.pausesLocationUpdatesAutomatically = false
manager.activityType = .other
manager.showsBackgroundLocationIndicator = false
}
func setupWidgetLocationManager() {
manager.requestWhenInUseAuthorization()
manager.startUpdatingLocation()
manager.startMonitoringSignificantLocationChanges()
}
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
if manager.authorizationStatus == .notDetermined || manager.authorizationStatus == .denied || manager.authorizationStatus == .restricted {
manager.stopUpdatingLocation()
manager.stopMonitoringSignificantLocationChanges()
}
if manager.authorizationStatus == .authorizedAlways || manager.authorizationStatus == .authorizedWhenInUse {
manager.startUpdatingLocation()
manager.startMonitoringSignificantLocationChanges()
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if let newestLocation = locations.last {
UserDefaults(suiteName: "group.com.***")?.set(Double(newestLocation.coordinate.latitude), forKey: "newest_location_latitude")
UserDefaults(suiteName: "group.com.***")?.set(Double(newestLocation.coordinate.longitude), forKey: "newest_location_longitude")
UserDefaults(suiteName: "group.com.***")?.set(Double(newestLocation.altitude), forKey: "newest_location_altitude")
WidgetCenter.shared.reloadAllTimelines()
}
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
}
}
Capability for background modes location is set, also mandatory strings in info.plist for location privacy info.
I have applied twice for Location Push service entitlement , the first time was last year and I forgot about it but I just checked my emails and I have found no response from apple at all , only the case-id from the automated email
and now I applied for it again and no response
can someone advice me what shall I do ??
my app really depends on it