Skip to content

Instantly share code, notes, and snippets.

@donnywals
Created May 22, 2024 06:38
Show Gist options
  • Save donnywals/f09317ab281b659c0ccfa4ea06d5d908 to your computer and use it in GitHub Desktop.
Save donnywals/f09317ab281b659c0ccfa4ea06d5d908 to your computer and use it in GitHub Desktop.
import SwiftUI
struct ContentView: View {
@State private var exercises: [Exercise] = Exercise.sample
var body: some View {
NavigationSplitView(sidebar: {
ExercisesList(exercises: exercises)
}, detail: {
ExerciseDetail(exercise: exercises.first!)
})
}
}
struct ExercisesList: View {
let exercises: [Exercise]
@State var activeItem: Exercise?
var body: some View {
List(exercises, id: \.id, selection: $activeItem) { exercise in
NavigationLink(value: exercise, label: {
ExerciseListItem(exercise: exercise)
})
}
.onAppear(perform: {
if activeItem == nil {
activeItem = exercises.first
}
})
.navigationTitle("My exercises")
// Need to use this one so we can get the iPad split view to work with list selection
.navigationDestination(item: Binding<Exercise?>(get: {
activeItem
}, set: { newValue in
// Use a custom binding to prevent unwanted deselection on iPad
guard let newValue else {
return
}
activeItem = newValue
}), destination: { exercise in
ExerciseDetail(exercise: exercise)
})
}
}
@matthewloewen
Copy link

I made some guesses about the nature of your project, but does this work the way you expect it to? It sets a default item, and it updates the detail with the current selection.

import SwiftUI
struct ContentView: View {
    @State private var exercises: [Exercise] = Exercise.sample
    @State private var activeItem: Exercise?
    
    var body: some View {
        NavigationSplitView(sidebar: {
            ExercisesList(exercises: exercises, activeItem: $activeItem)
        }, detail: {
            if let activeItem {
                ExerciseDetail(exercise: activeItem)
            } else {
                Text("Please select an exercise")
                    .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center)
            }
        })
        .task {
            activeItem = exercises.first
        }
    }
}

struct ExercisesList: View {
    let exercises: [Exercise]
    @Binding var activeItem: Exercise?
    
    var body: some View {
        List(exercises, id: \.id, selection: $activeItem) {
            ExerciseListItem(exercise: $0)
                .tag($0)
        }
    }
}

struct ExerciseListItem: View {
    let exercise: Exercise
    
    var body: some View {
        VStack(alignment: .leading) {
            Text(exercise.type.rawValue.capitalized)
            Text(exercise.date.formatted(date: .numeric, time: .omitted))
        }
    }
}

struct ExerciseDetail: View {
    let exercise: Exercise
    
    var body: some View {
        Form {
            LabeledContent("Type", value: exercise.type.rawValue.capitalized)
            LabeledContent("Date", value: exercise.date.formatted(date: .long, time: .shortened))
            LabeledContent("Reps", value: exercise.count.formatted())
        }
    }
}

struct Exercise: Identifiable, Hashable {
    let id = UUID()
    var type: ExerciseType
    var count: Int
    var date: Date
    
    static var sample: [Exercise] = [
        .init(type: .pushup, count: 10, date: .now),
        .init(type: .crunch, count: 14, date: Calendar.current.date(byAdding: .day, value: -1, to: .now)!),
        .init(type: .jumpingJack, count: 14, date: Calendar.current.date(byAdding: .day, value: -2, to: .now)!),
    ]
}


enum ExerciseType: String {
    case pushup, crunch, jumpingJack
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment