Home > OS >  Undestranding @State SwiftUI
Undestranding @State SwiftUI

Time:10-12

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?

enter image description here


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
    }
}
  • Related