Post not yet marked as solved
I need to hide or remove gps indicator from status bar/ navigation bar on background mode. I have already used locationManager?.showsBackgroundLocationIndicator = false but it doesn't when user select "While using the app".
Post not yet marked as solved
The beacon device is very close to the phone(ios17).
But the RSSI obtained from the beacon information returned by the locationManager's didRange function is always 0. Why?
log:
didRange [CLBeacon (uuid:D4C3CCC0-29FB-11E5-884F-0002A5D5C51B, major:0, minor:9, proximity:0 +/- -1.00m, rssi:0, timestamp:2024-02-15 06:48:57 +0000)]
didRange [CLBeacon (uuid:D4C3CCC0-29FB-11E5-884F-0002A5D5C51B, major:0, minor:9, proximity:0 +/- -1.00m, rssi:0, timestamp:2024-02-15 06:48:58 +0000)]
didRange [CLBeacon (uuid:D4C3CCC0-29FB-11E5-884F-0002A5D5C51B, major:0, minor:9, proximity:0 +/- -1.00m, rssi:0, timestamp:2024-02-15 06:48:59 +0000)]
didRange [CLBeacon (uuid:D4C3CCC0-29FB-11E5-884F-0002A5D5C51B, major:0, minor:9, proximity:0 +/- -1.00m, rssi:0, timestamp:2024-02-15 06:49:00 +0000)]
Post not yet marked as solved
Hi Developers. I need to try to embed GeoData into a USDZ model and then have the capabilities to "explore" the model while walking around in the real world.
e.g. load and display a 3D model of Time Square and show a location pin which displays a users' virtual position on the model... when the user walks 10 meters north, in the real world, the location pin must move 10m (to scale) on the displayed model.
As a new developer, I'm starting from scratch so would benefit greatly from having my hand held - please don't be afraid of patronizing me.
Step 1 - load and display the 3D model
Step 2 - geolocate the user
Step 3 - translate the user's current position into a position on the 3D model and represent their "position" on the model with a traditional GPS location marker "pin".
Step 4 - move the user's GPS pin on the mode, relative to (and reflecting) their actual real world movement.
Is this acheivable or have I explained things to ambiguously?
I look forward to hearing from my savior(s) as soon as convenient.
Thank you in advance
Post not yet marked as solved
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
Post not yet marked as solved
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
Post not yet marked as solved
I'm trying to develop a watchOS app with location.
I've got the proper privacy settings in the info.plist, similar code works on other devices. (also simulators).
But on watchOS simulators everything is grayed out.
Privacy & Location -> Location Services
App shows up correctly, but everything is grayed out.
I've tried:
Different simulators (with/without paired iPhone)
Different app configurations (Watch-Only app, Watch App with new companion)
Toggling Supports Running Without iOS App Installation.
It's always grayed out!
This is with watchOS 10 simulators across any model, and Xcode 15.2
Any help would be appreciated.
Post not yet marked as solved
I found something when I use CLLocationManagerDelegate on VisionOS.
When I called func locationManagerDidChangeAuthorization
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
switch manager.authorizationStatus {
case .notDetermined, .denied:
locationManager.requestWhenInUseAuthorization()
default:
locationManager.startUpdatingLocation()
guard let center = locationManager.location?.coordinate else { return }
isFollowing = false
mapCamera = .region(.init(center: center, span: .init(latitudeDelta: 0.005, longitudeDelta: 0.005)))
addItems()
}
}
Although I choose allow auth, locationManagerDidChangeAuthorization wasn't called.
Post not yet marked as solved
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()
}
}
}
Post not yet marked as solved
Which mode uses the least battery? The docs don't say much at all about the modes.
default
airborne
automotiveNavigation
fitness
otherNavigation
Some background is that they all result in location updates every 1s, I would gladly trade battery performance for less frequent updates.
Post not yet marked as solved
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)
Post not yet marked as solved
I activate the conditions as follows
Unexpected operation found. Details are below
Conditions and configurations used in the testing
"Background Modes" Capability with "Location updates" checked on
added the info.plist keys: NSLocationAlwaysAndWhenInUseUsageDescription, NSLocationWhenInUseUsageDescription with description
invoking startMonitoringSignificantLocationChanges using core location API
invoking didUpdateLocations using core location API
Using Background fetch (15 minutes)
I just press the Home button without any gesture.
A few hours after the app was stopped, didfinishlaunch, didenterBackground, background fetch, and didUpdateLocation code did not run, but the app started running again in the background from the point it was stopped.
The wake-up time is random, and the app will freeze again within a few seconds of running again.(I took logs in all delegate functions related to the app life cycle in the AppDelegate file, but nothing was executed when the app was relaunched.) Is the above behavior normal?
If it's normal, who wakes up the app? How do I prevent my app from restarting unexpectedly?
Post not yet marked as solved
Hello,
I have successfully used the getCoordinates() function provided by Apple Documentation to convert an address to coordinates. I created my own struct for a Pin that includes name, latitude, and longitude as properties.
I am able to add Markers to my map using these three properties. My problem is that I'd like to use these Markers to pull up further information, such as lookaround views. To use these API call functions, I need to provide an MKMapItem as an argument to the mapItem parameter.
MKLookAroundSceneRequest(mapItem: MKMapItem)
I'm having trouble using the MKMapItem documentation to understand how to make my own MKMapItems.
If I try using the autocomplete in XCode, I can get this:
MKMapItem(placemark: MKPlacemark(coordinate: CLLocationCoordinate2D(latitude: latitude, longitude: longitude)))
Is it possible to add a name when instantiating a new MKMapItem? From the documentation, it seems like name is a property of MKPlacemark, but I can't get this to work.
Should I alter the getCoordinates() function to return the entire placemark instead of just the coordinates?
Any guidance would be much appreciated! Thanks!
Post not yet marked as solved
Hi,
The ARkit is a great tool, I have my small app doing things, and it's fun!
but I wanted to try to migrate from ARWorldConfiguration to ARGeoTrackingConfiguration - https://developer.apple.com/documentation/arkit/argeotrackingconfiguration
and then we can see that this configuration is limited to a couples of USA only cites.
But I can't manage to figure Why and if, in the near future, this will be expanded world wide ?
Post not yet marked as solved
I have used this example to create the following code:
import Foundation
import CoreLocation
let monitorName = "BeaconMonitor"
let testBeaconId = UUID(uuidString: "EDFA3FFA-D80A-4C23-9104-11B5B0B8E8F3")!
@MainActor
public class ObservableMonitorModel: ObservableObject {
private let manager: CLLocationManager
public var monitor: CLMonitor?
init() {
self.manager = CLLocationManager()
self.manager.requestWhenInUseAuthorization()
self.manager.requestAlwaysAuthorization()
}
func startMonitoringConditions() {
Task {
monitor = await CLMonitor(monitorName)
await monitor!.add(getBeaconIdentityCondition(), identifier: "Beacon")
for identifier in await monitor!.identifiers {
guard let lastEvent = await monitor!.record(for: identifier)?.lastEvent else { continue }
print(identifier, lastEvent.state)
}
for try await event in await monitor!.events {
print("Event", event.identifier, event)
}
}
}
}
func getBeaconIdentityCondition() -> CLMonitor.BeaconIdentityCondition {
CLMonitor.BeaconIdentityCondition(uuid: testBeaconId)
}
Unfortunately, running this on my iPhone only prints "Beacon CLMonitoringState". I don't see anything from the for try await block starting with "Event".
Any ideas where I've gone wrong?
Post not yet marked as solved
I activate the conditions as follows
Unexpected operation found. Details are below
Conditions and configurations used in the testing
"Background Modes" Capability with "Location updates" checked on
added the info.plist keys: NSLocationAlwaysAndWhenInUseUsageDescription, NSLocationWhenInUseUsageDescription with description
invoking startMonitoringSignificantLocationChanges using core location API
invoking didUpdateLocations using core location API
Using Background fetch (15 minutes)
I swipe the app to switch from foreground to background mode, and stop the app without deleting it in the switcher.
A few hours after the app was stopped, didfinishlaunch, didenterBackground, background fetch, and didUpdateLocation code did not run, but the app started running again in the background from the point it was stopped.
The wake-up time is random, and the app will freeze again within a few seconds of running again.(I took logs in all delegate functions related to the app life cycle in the AppDelegate file, but nothing was executed when the app was relaunched.)
Is the above behavior normal?
If it's normal, who wakes up the app?
How do I prevent my app from restarting unexpectedly?
Post not yet marked as solved
Hi everyone,
I've run into an issue with push notifications in our app, specifically those related to the location push service extension. In the Push Notifications Console, there's a high number of notifications marked as “Discarded - Disabled” under Location Notifications. I'm trying to figure out what's causing this. We are seeing thousands of “Discarded - Disabled” for location but the other push types are being discarded in much smaller numbers (in the tens).
Here's what I need help with:
What do the different 'Discarded' categories mean in push notifications? Which are normal and which are red flags?
Why are so many Location Notifications being discarded as 'Disabled'? Is this a common device setting issue?
Any tips on reducing these discarded notifications, especially for location-based services?
Would really appreciate your insights or any pointers towards relevant resources!
Thanks!
LC
Post not yet marked as solved
When I run CLMonitor in the simulator, event state remains at default. Although when running the same project on device, state does correctly change between satisfied and unsatisfied.
In the simulator I did allow location updates when in use as I did on device.
This occurs with the Apple sample code, Monitoring location changes with Core Location associated with the WWDC 2023 session Meet Core Location Monitor.
Am I misusing simulator and/or CLMonitor?
Post not yet marked as solved
@MainActor
perform() async throws -> some IntentResult {
// ...
switch locationManager.authorizationStatus {
case .denied, .restricted:
throw UserLocationError.permissionDenied
case .notDetermined:
await locationManager.requestWhenInUseAuthorization() // to ask permission
default:
break
}
// ...
}
Here is my code.
When the authorizationStatus is .notDetermined,
it invokes requestWhenInUseAuthorization() method on the main thread,
but throws UserLocationError.permissionDenied immediately, eventhough I didn't deny the permission.
It's really weird and unexpected that it throws UserLocationError.permissionDenied when the status is not .denied or .restricted
Even it invokes requestWhenInUseAuthorization(), there's no alert for asking permission
If there's any solution, please let me know
Post not yet marked as solved
This is my setup:
Granted always allow permission.
I have location added in UIBackgroundModes, but I did NOT set allowsBackgroundLocationUpdates to true
Note: I have this allowsBackgroundLocationUpdates = true set in my earlier version of app, which worked but we noticed it drained battery much faster, hence we removed all the settings that could affect battery.
The location model is setup with 20 regions, when boundary crossing happen, app sends a local notification. This works fine when app is in foreground/background. If app is killed, the app receives notification for boundary crossing only once.
Failed case for region monitoring:
Setup region monitoring
Kill the app
cross the boundary, app sends a local notification.
wait for 1 hour
leave the device in same state (notification is not opened, app is still killed state)
cross the boundary again
expect a notification, but app did not register any event related to region monitoring.
The console logs did not print anything in this second case.
public class LocationViewModel: NSObject, ObservableObject {
private let maxMonitoredRegions = 20
private var anyCancellable: AnyCancellable?
private let locationManager: CLLocationManager
@Published public var authorizationStatus: CLAuthorizationStatus
@Published public var isMonitoringAvailable: Bool
@Published public var monitoredRegions: [Region]
@Published public var recentLocation: CLLocation?
public var newlyEnteredRegionSignal = PassthroughSubject<CLRegion, Never>()
public var recentLocationSignal = PassthroughSubject<CLLocation, Never>()
public var authorizationStatusPublisher: Published<CLAuthorizationStatus>.Publisher { $authorizationStatus }
public var isLocationEnabled: Bool {
locationManager.authorizationStatus == .authorizedWhenInUse ||
locationManager.authorizationStatus == .authorizedAlways
}
public override init() {
locationManager = CLLocationManager()
authorizationStatus = locationManager.authorizationStatus
isMonitoringAvailable = CLLocationManager.isMonitoringAvailable(for: CLCircularRegion.self)
monitoredRegions = []
super.init()
locationManager.delegate = self
monitoredRegions.append(contentsOf: getMonitoredRegions())
requestLocation()
}
public func requestLocation() {
locationManager.requestLocation()
}
public func startRegionMonitoring(regions: [CLRegion]) {
guard isMonitoringAvailable else {
return
}
stopRegionMonitoring()
if regions.isEmpty {
return
}
if regions.count <= 20 {
for region in regions {
locationManager.startMonitoring(for: region)
}
} else {
for region in regions[0...maxMonitoredRegions-1] {
locationManager.startMonitoring(for: region)
}
}
}
public func stopRegionMonitoring() {
guard isMonitoringAvailable else {
return
}
if monitoredRegions.isEmpty {
return
}
for region in monitoredRegions {
let monitoredRegion = LocationUtils.convertRegionToCLRegion(region)
locationManager.stopMonitoring(for: monitoredRegion)
}
monitoredRegions.removeAll()
}
private func getMonitoredRegions() -> [Region] {
let monitoredRegions = locationManager.monitoredRegions
var regions = [Region]()
for monitoredRegion in monitoredRegions {
if let region = LocationUtils.convertCLRegionToRegion(monitoredRegion) {
regions.append(region)
}
}
return regions
}
public func stopMonitoring() {
recentLocation = nil
stopRegionMonitoring()
}
}
extension LocationViewModel: CLLocationManagerDelegate {
public func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
authorizationStatus = manager.authorizationStatus
switch authorizationStatus {
case .notDetermined:
stopMonitoring()
case .denied:
stopMonitoring()
case .authorizedAlways:
break
case .authorizedWhenInUse:
// If user has requested whenInUse, request for always allow.
locationManager.requestAlwaysAuthorization()
@unknown default:
break
}
if let location = manager.location {
recentLocationSignal.send(location)
recentLocation = location
}
}
public func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if let recentLocation = locations.last {
self.recentLocation = recentLocation
recentLocationSignal.send(recentLocation)
}
}
public func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
}
public func locationManager(_ manager: CLLocationManager, didStartMonitoringFor region: CLRegion) {
if let monitoredRegion = LocationUtils.convertCLRegionToRegion(region) {
let oldRegion = monitoredRegions.first {
$0.identifier == monitoredRegion.identifier
}
if oldRegion == nil {
monitoredRegions.append(monitoredRegion)
}
}
}
public func locationManager(_ manager: CLLocationManager, monitoringDidFailFor region: CLRegion?, withError error: Error) {
}
public func locationManager(_ manager: CLLocationManager, didEnterRegion region: CLRegion) {
newlyEnteredRegionSignal.send(region)
}
public func locationManager(_ manager: CLLocationManager, didExitRegion region: CLRegion) {
newlyEnteredRegionSignal.send(region)
}
}
When app is awaken due to location event on app delegate, we initialize this location model, and location manager, and remove old monitored regions, and call startMonitoringRegions again, to keep the regions updated.
Please let me know if I'm missing any crucial information.
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