I created an app that fetches bike parking spots around me. In the app, every thing works perfectly.
Now, I'm trying to create a shortcut that triggers the fetching of the parking spots. Unfortunately, it doesn't work. Everytime, I get a crash.
Here is a partial code of the MapView where I can fetch the spots :
struct MapView: View {
@State private var position: MapCameraPosition = .userLocation(fallback: .region(LocationManager().region))
@State var manager = LocationManager()
@State var visibleRegion: MKCoordinateRegion?
@Namespace var mapScope
var body: some View {
Map(position: $position, selection: $selectedParkedBike, scope: mapScope){
// Some code to display fetched parking spots
}
.ignoresSafeArea()
.mapControls {
}
.onAppear {
visibleRegion = manager.region
}
// Some code
func fetchParkingSpotsForVisibleRegion(medium: String) {
let (lat, long) = (visibleRegion!.center.latitude, visibleRegion!.center.longitude)
let visibleRegion = visibleRegion!
// Some code
}
And here is my App Intent code
struct TriggerSearchIntent: AppIntent {
static let title: LocalizedStringResource = "Recherche un emplacement pour mon vélo"
@MainActor
func perform() async throws -> some IntentResult {
let mapView = MapView()
mapView.fetchParkingSpotsForVisibleRegion(medium: "shortcut")
return .result()
}
static let openAppWhenRun: Bool = true
}
When using the shortcut, I got the error that visibleRegion
= nil
, I don't really get why has the visibleRegion is set when the map is appearing.
To solve this I tried a to set visibleRegion
into the App Intent code, and tried many other things that all failed 😕
I found a way to make it work :
In my App Intent, I send a notification to the app :
struct TriggerSearchIntent: AppIntent {
static let title: LocalizedStringResource = "Recherche un emplacement pour mon vélo"
static let openAppWhenRun: Bool = true
@MainActor
func perform() async throws -> some IntentResult {
NotificationCenter.default.post(name: Notification.Name(rawValue: "performSearchFromShortcut"), object: nil)
return .result()
}
}
In the app, when receiving the notification I perform the function:
struct MapView: View {
@State private var position: MapCameraPosition = .userLocation(fallback: .region(LocationManager().region))
@State var manager = LocationManager()
@State var visibleRegion: MKCoordinateRegion?
@Namespace var mapScope
var body: some View {
Map(position: $position, selection: $selectedParkedBike, scope: mapScope){
// Some code to display fetched parking spots
}
.ignoresSafeArea()
.mapControls {
}
.onAppear {
visibleRegion = manager.region
}
.onReceive(NotificationCenter.default.publisher(for: Notification.Name(rawValue: "performSearchFromShortcut"))) { notification in
fetchParkingSpotsForVisibleRegion(medium: "shortcut")
}
// Some code
func fetchParkingSpotsForVisibleRegion(medium: String) {
let (lat, long) = (visibleRegion!.center.latitude, visibleRegion!.center.longitude)
let visibleRegion = visibleRegion!
// Some code
}
And voilà!