Hello. I am building an app that shows my walk workouts and in the detail view I want to show the route I took while walking, similar to that of the Apple Fitness App. There is a problem though, I cannot seem to understand how to connect the @State property workoutLocations array that would be used to draw the route on the map with what I get from the query. The task does successfully fetches the data but then when I try to use it later in a do-catch block nothing happens. What am I missing here?
import SwiftUI
import MapKit
import HealthKit
struct DetailView: View {
@Environment(HealthKitManager.self) var healthKitManager
let workout: HKWorkout
@State private var workoutLocations: [CLLocation] = []
var body: some View {
ScrollView {
//...
}
.task {
guard let store = self.healthKitManager.healthStore else {
fatalError("healthStore is nil. App is in invalid state.")
}
let walkingObjectQuery = HKQuery.predicateForObjects(from: workout)
let routeQuery = HKAnchoredObjectQueryDescriptor(predicates: [.workoutRoute(walkingObjectQuery)], anchor: nil)
let queryResults = routeQuery.results(for: store)
let task = Task {
var workoutRouteLocations: [CLLocation] = []
for try await result in queryResults {
let routeSamples = result.addedSamples
for routeSample in routeSamples {
let routeQueryDescriptor = HKWorkoutRouteQueryDescriptor(routeSample)
let locations = routeQueryDescriptor.results(for: store)
for try await location in locations {
workoutRouteLocations.append(location)
print(workoutRouteLocations.count) // this prints out the number of locations in the sample.
}
}
}
return workoutRouteLocations
}
do {
print(try await task.value.count) // this prints nothing. Therefore if I try to update workoutLocations array from here it would do nothing as well
// workoutLocations = try await task.value therefore does nothing and the array just doesn't get populated with the results of the task
} catch {
print(error)
}
}
}
}
Post
Replies
Boosts
Views
Activity
I am just starting to build a new app but I have already run into some weird problem. I created a custom button as a separate view. On the preview the button looks as expected:
The code for the view above looks like this:
struct LeagueSelectorButton: View {
let text: String
let leagueID: Int
@Binding var isSelected: Bool
var body: some View {
HStack {
leagueLogo
leagueName
}
.padding(10)
.background {
RoundedRectangle(cornerRadius: 6)
.stroke(isSelected ? .green : .black, lineWidth: 3)
}
.onTapGesture {
isSelected.toggle()
}
}
var leagueLogo: some View {
AsyncImage(url: URL(string: "https://media.api-sports.io/football/leagues/\(leagueID).png")) { image in
image
.resizable()
.frame(width: 35, height: 35)
} placeholder: {
Rectangle()
.frame(width: 35, height: 35)
}
}
var leagueName: some View {
Text("\(text)")
.bold()
.font(.title)
}
}
But when I use this custom button in a different view it starts to look weird as you can see. The corners are all wrong and line widths are all over the place:
The code for this view is the following:
struct GamesView: View {
@State var isSelected = false
var body: some View {
ScrollView {
VStack {
ScrollView(.horizontal) {
HStack {
LeagueSelectorButton(text: "Premier League", leagueID: 39, isSelected: $isSelected)
}
}
.scrollIndicators(.hidden)
.padding()
// ...
// other code that doesn't matter
}
}
}
}
Help me out here. I don't really understand what I am doing wrong here.
As I was watching WWDC19 Session: "LLDB: beyond "po" " I got confused about "p" command. In the session there was a following example to show how "p" command works:
// Struct for demonstration purposes
struct Trip {
var name: String
var destinations: [String]
let cruise = Trip (
name: "Mediterranean Cruise"
destinations: ["Sorrento", "Capri", "Taormina"])
Using "p" to get info about cruise instance:
(lldb) p cruise
(Travel.Trip) $R0 = {
name = "Mediterranean Cruise"
destinations = 3 values {
[0] = "Sorrento"
[1] = "Capri"
[2] = "Taormina"
}
}
I was following along and wrote the same code. But the output from LLDB turned out to be different:
(lldb) p cruise
(LLDB_Apple_Session_FollowAlong.Trip) {
name = "Mediterranean Cruise"
destinations = 3 values {
[0] = "Sorrento"
[1] = "Capri"
[2] = "Taormina"
}
}
As you can see LLDB didn't create a global variable R0 which I could later use in my debugging session and that seemed strange to me.
Then the presenter said the following:
"p" is just an alias for the "expression" command.
So, I tried to use the "expr" command to see if they're actually the same and they turned out to be different commands. The output I got from "expr" was the one I expected from "p":
(lldb) expr cruise
(LLDB_Apple_Session_FollowAlong.Trip) $R0 = {
name = "Mediterranean Cruise"
destinations = 3 values {
[0] = "Sorrento"
[1] = "Capri"
[2] = "Taormina"
}
}
Finally, my question is:
Am I wrong somewhere or did something change in LLDB regarding "p" and "expr" commands and if so, where could I get more information about the changes?