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
Post
Replies
Boosts
Views
Activity
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
Can Mapkit show me details about bus stops, train stations, underground and overground stops, or other public transportation locations based on a specific latitude and longitude?
If you check the Google Maps picture I shared, I marked all the public transportation spots near Elephant & Castle in London. This includes bus stops, the Elephant & Castle Underground station, and the Elephant & Castle Rail station. Additionally, tapping on these spots brings up an alert with more info, like which buses are coming or details about train lines.
Does any Apple API support the Location management for the business?
I am interested in if I am able to integrate an Apple business into my application.
The first thing I care about is business location management (I would like to create/edit the location via an API call)
In our placation there are instances of crashes that are happening in production. That we cannot quite reproduce. Looking at the crash report doesn't reveal much as the crashed thread doesn't give too much information of where to look for the root cause of the problem. In our app we are also using third-party libraries but I didn't see that they might be the cause for the crash.
Crash report
If someone can point me in the right direction to look for or how to investigate it. It would much appreciated.
Hello.
I've submitted a small update for my app and i
received an email that said: "The “” value for the
NSLocationWhenInUseUsageDescription key isn’t allowed
"
I have values for the above key in English and Greek in
InfoPlist files and they are appearing correctly when the
app is asking for location permissions. It has been like this
for years and i didn't change anything related to
this function.
Can someone please explain to me why i received this email
although i've set everything correctly?
Is there a way of deleting an app from the Location Services in the Privacy Setting?
Despite deleting the particular app evidence of it remains.
Also with a particular app there are several of the same in the list. I do understand there may be one for the Playgrounds version and one for the actual downloaded version but I have more.
Is there a way of starting with a clean slate?
After installing 17.1 on test devices, I am seeing a lengthy difference in requesting a user location. Takes about 4-5 seconds. This issue doesn't occur on 16 or 17.0. Anyone else seeing this problem?
If you refresh the page after initially granting location permissions, you will be prompted for location permissions again and will need to grant permission again. Currently this only occurs on iOS. Is there a way?
The tested iOS versions are 16.2 and 17.
This is the code implemented when retrieving location information.
<script>
var options = {
timeout: 15000,
enableHighAccuracy: true,
maximumAge: 86400000,
};
function success(pos) {
var crd = pos.coords;
alert('Your current position is:');
alert(`Latitude : `+crd.latitude);
alert(`Longitude: `+crd.longitude);
};
function error(err) {
alert(`ERROR(): `+err.message);
};
navigator.geolocation.getCurrentPosition(success, error, options);
</script>
If you refresh the page after initially granting location permissions, you will be prompted for location permissions again and will need to grant permission again. Currently this only occurs on iOS. Is there a way?
I launched that web from app and the Safari settings didn't fix the issue. What should I do about this problem?
The tested iOS versions are 16.2 and 17.
This is the code implemented when retrieving location information.
<script>
var options = {
timeout: 15000,
enableHighAccuracy: true,
maximumAge: 86400000,
};
function success(pos) {
var crd = pos.coords;
alert('Your current position is:');
alert(`Latitude : `+crd.latitude);
alert(`Longitude: `+crd.longitude);
};
function error(err) {
alert(`ERROR(): `+err.message);
};
navigator.geolocation.getCurrentPosition(success, error, options);
</script>
At the moment with my app Users have to go to Privacy & Security -> Locations Services -> On -> Scroll down to my app and turn on their Location Preference.
I am trying to incorporate in to my app the Code below to make it unecessary to leave the app to enable the User‘s location to be displayed but it does not work.
Please tell me, what am I missing here?
import MapKit
import SwiftUI
import CoreLocation
// Prompt User to choose Location Preference //
class ViewController: UIViewController, CLLocationManagerDelegate{
var locationManager: CLLocationManager?
override func viewDidLoad() {
super.viewDidLoad()
locationManager = CLLocationManager()
locationManager?.delegate = self
locationManager?.requestWhenInUseAuthorization()
view.backgroundColor = .gray
}
}
// The rest of the Code which is working okay ( Map etc.) //
struct Positions: Identifiable {
let id = UUID()
let name: String
let latitude: Double
let longitude: Double
var coordinate: CLLocationCoordinate2D {
CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
}
}
etc.
etc.
I have a map (iOS 17) that displays the three Apple maps types (standard, hybrid, and imagery). When the hybrid or imagery map is displayed for the first time it is zoomed in to the max and out-of-focus. It appears to be a problem with the span. I would like to set the span to fix this, but I'm not sure if span has a new name or is no longer used.
In previous versions of iOS I had a region that defined the span and coordinate center, It appears that this has now been deprecated:
let span = MKCoordinateSpan(latitudeDelta: 0.005, longitudeDelta: 0.005)
let region = MKCoordinateRegion(center: coordinate, span: span)
MapView(region: region, mapType: mapType, coordinate: coordinate)
Here is my actual code for display a map (iOS 17):
struct DetailView: View {
var item: TravelEntries // <-- coordinates arrive from CoreData Transaction
@Binding var mapType: Int
var coordinate: CLLocationCoordinate2D {
CLLocationCoordinate2D(
latitude: item.entryLat,
longitude: item.entryLong)
}
var selectedMapStyle: MapStyle {
return switch(mapType) {
case 0: .standard(elevation: .realistic)
case 1: .hybrid
case 2: .imagery
default: .standard(elevation: .realistic)
}
}
var body: some View {
VStack {
Map() {
Marker(item.entryCatName ?? "", coordinate: coordinate)
.tint(.red)
}
.mapStyle(selectedMapStyle)
ShowMapPicker(item: item, mapType: $mapType)
ShowDetails(item: item)
}
}
}
I have a new app that I am starting using the Map() component in iOS17. That struct, creates a class which is a CLLocationManagerDelegate, and instantiates a CLLocationManager. In the Target's Info settings, I have
Privacy - Location Always and When In Use Usage Description
Privacy - Location Always Usage Description
Privacy - Location Usage Description
all three set.
I have another Map app with these set which doesn't have this problem, so I am confused about why, in Privacy & Security->Location Services, the App only shows two selections for Location Services. It shows only "Never" and "When I Share" selections with "When I Share" selected. The location manager reports
error: The operation couldn’t be completed. (kCLErrorDomain error 1.)
after I get the
CLAuthorizationStatus(rawValue: 0) auth=CLAccuracyAuthorization(rawValue: 0)
value in
public func locationManagerDidChangeAuthorization(_ manager: CLLocationManager)
status change in this callback for the delegate and then call:
manager.requestAlwaysAuthorization()
manager.startUpdatingLocation()
What am I missing here?