Hi everyone I have a problem understanding @State in swiftUI
I'll explain better ... As you can see from the image inside a scrollView I have two Views, one contains a calendar and another contains the summary of the user's day selection.
Now ... I used to update the summaryView with the day selected by the user on the calendar
@State private var selectedDate: Date = Self.now
private static var now = Date ()
Also in the View that contains the summary of the user's selection (view above the calendar) there is also a random yellow string created with a function
// MARK: - Generate Random String
private extension Reservations {
func generateRandomString(length: Int) -> String {
let letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
var s = ""
for _ in 0 ..< length {
s.append(letters.randomElement()!)
}
return s
}
}
which changes every time the user selects a day on the calendar.
My problem is that when the user selects a calendar day the app only has to change the date in the summary view and doesn't have to repeat the "randomString" function again
This problem is due to using @State did I understand correctly? what should I use instead of @State to change a single value that is not in the same View?
struct Reservations: View {
@Environment(\.calendar) private var calendar
@State private var selectedDate: Date = Self.now
private static var now = Date()
var body: some View {
Summary()
ReservationsCalendar()
}
}
// MARK: - Generate Random String
private extension Reservations {
func generateRandomString(length: Int) -> String {
let letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
var s = ""
for _ in 0 ..< length {
s.append(letters.randomElement()!)
}
return s
}
@ViewBuilder func Summary() -> some View {
HStack(spacing: 10) {
HStack {
Text(selectedDate.dayFormatted(style: .twoDigits))
.font(.title.bold())
Text("ID").foregroundColor(.white)
Text(generateRandomString(length: 7).uppercased())
.foregroundColor(.yellow)
.padding(.horizontal, 10)
.frame(height: 25)
.background(
Capsule()
.fill(.black.opacity(0.2))
)
}
}
}
@ViewBuilder private func ReservationsCalendar() -> some View {
ReservationsCal(currentDate: $selectedDate)
}
}
CodePudding user response:
Right now, you call generateRandomString
in your view hierarchy, guaranteeing that it'll generate a new random string every time the view is re-rendered.
Instead, you could declare it as a @State
variable, which will persist across re-renders (and declare generateRandomString
so it can be used during the init phase):
struct Reservations: View {
@State private var selectedDate: Date = Self.now
@State private var randomString = Self.generateRandomString(length: 7)
private static var now = Date()
var body: some View {
Text(randomString.uppercased())
}
}
private extension Reservations {
static func generateRandomString(length: Int) -> String {
let letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
var s = ""
for _ in 0 ..< length {
s.append(letters.randomElement()!)
}
return s
}
}