I'm fairly new to SwiftUI. I'm trying to build an app that is specific for iPads that has a view containing a list of items (clients) where I would like to load the selected client into the detail view within the same view. I wanted to avoid using NavigationStack because I don't want the iPad native UX, I just want to load the selected client data into the ClientDetail() view.
Here is what I have:
Getting client data when tapping
If I set 'selectedClient' explicitly the ClientDetail() view loads properly when tapping through the list. But I want no selection when the ActivityView() first loads into view.
@State private var selectedClient = Client(name: "Tom", room: "1", time: "0200", status: "Active")
With the below code I have no errors in Xcode but crashes the app with "Implicitly unwrapped nil value in ActivityView.swift"
@State private var selectedClient = Client?(nil)
var body: some View {
ZStack {
ClientDetail(client: selectedClient!)
ActivityView():
import SwiftUI
struct ActivityView: View {
@EnvironmentObject var model: ClientViewModel
@State private var selectedClient = Client?(nil)
var body: some View {
ZStack {
ClientDetail(client: selectedClient!)
// ACTIVE CLIENT LIST
VStack(alignment: .center, spacing: 50) {
ScrollView {
ForEach(model.clients) { client in
Button {
selectedClient = client
print(client)
} label: {
HStack(alignment: .center, spacing: 20) {
Circle()
.fill(Color.accentColor)
.frame(width: 14, height: 14)
.offset(y: -10)
VStack(alignment: .leading, spacing: 5) {
Text(client.name)
.customFont(.title3)
.foregroundColor(.white)
.lineLimit(1)
Text("Room \(client.room) · \(client.time)")
.font(.subheadline)
.fontWeight(.medium)
.foregroundColor(.white)
.opacity(0.6)
} //: VSTACK
Spacer()
} //: HSTACK
.padding(.horizontal, 30)
.padding(.vertical, 18)
}
}
}
Spacer()
} //: VSTACK
.frame(maxWidth: 294, maxHeight: .infinity)
.background(CustomColor.lightBlueColor)
.padding(.leading, 120)
.frame(maxWidth: .infinity, alignment: .leading)
}
}
}
struct ActivityView_Previews: PreviewProvider {
static var previews: some View {
ActivityView()
.environmentObject(ClientViewModel())
.previewInterfaceOrientation(.landscapeRight)
}
}
ClientViewModel():
import Foundation
final class ClientViewModel: ObservableObject {
@Published var clients = [Client]()
let testClients = [
Client(name: "Tyler Goodman", room: "1", time: "2:00pm", status: "active"),
Client(name: "Jeffery Day", room: "2", time: "2:00pm", status: "active"),
Client(name: "Troy Roberts", room: "5", time: "1:45pm", status: "active"),
Client(name: "Helen Carr", room: "3", time: "1:30pm", status: "active"),
Client(name: "Albert Perry", room: "6", time: "1:30pm", status: "active"),
Client(name: "Marvin Cross", room: "1", time: "1:15pm", status: "active"),
Client(name: "Sarah Ryan", room: "2", time: "1:00pm", status: "active"),
Client(name: "Mason Ortega", room: "4", time: "12:45pm", status: "active")
]
init() {
self.clients = testClients
}
}
struct Client: Identifiable {
var id = UUID().uuidString
var name: String
var room: String
var time: String
var status: String
}
Any pointers on this would be much appreciated. Thank you.
I've tried
@State private var selectedClient = Client?(nil)
@State private var selectedClient = Client? = nil
Get the same resulting error
This line is crashing if selectedClient
is nil
:
ClientDetail(client: selectedClient!)
because with !
you force unwrap.
It should be
@State private var selectedClient: Client? = nil
and in ActivityView:
if let selectedClient { // unwrap optional client
ClientDetail(client: selectedClient)
} else {
Text("Select a client")
}