Allowing only one box to be checked

I'm running into an issue where I'm trying to do two things

  1. Uncheck an existing checkbox when another one is checked. Basically only allow for one state to be active.

  2. When I have one boxed checked every box is showing checked when the pages appears as a sheet.

Here's a repro of what i'm working on.

Code Block
struct Themes: View {
  var body: some View {
    List {
      ForEach (themeData) { themedata in
        ThemesView(themedata: themedata)
      }
      .padding()
    }
  }
}
struct ThemesView: View {
  var themedata: themes
  @State var themedCheck = UserDefaults.standard.bool(forKey: "ThemeChecked")
  @State var themeColorUserSetting = UserDefaults.standard.string(forKey: "ThemeColor")
  @State var themeColor = "card3"
  var body: some View {
    HStack(spacing: 16) {
      Circle()
        .fill(Color(themedata.color))
        .frame(width: 25, height: 25, alignment: .center)
      Text(themedata.name)
        .font(.custom("ProximaNova-Regular", size: 18))
      Text("\(self.themeColor)")
      Spacer()
      ZStack {
        RoundedRectangle(cornerRadius: 7)
          .stroke(style: StrokeStyle(lineWidth: 1.5))
          .frame(width: 35, height: 35)
          .foregroundColor(themedCheck ? Color("card2") : Color.gray.opacity(0.2))
        RoundedRectangle(cornerRadius: 7)
          .trim(from: 0, to: 1)
          .fill(themedCheck ? Color("card2") : Color.gray.opacity(0.2))
          .frame(width: 25, height: 25)
        if themedCheck {
          Image(systemName: "checkmark")
            .foregroundColor(Color.white)
        }
      }
      .onTapGesture{
        if !self.themedCheck {
          withAnimation(Animation.easeIn(duration: 0.5)) {
            self.themedCheck.toggle()
            UserDefaults.standard.set(self.themedCheck, forKey: "ThemeChecked")
            UserDefaults.standard.set(self.themeColorUserSetting, forKey: "ThemeColor")
            self.themeColor = themedata.color
          }
        } else {
          withAnimation{
            self.themedCheck.toggle()
            UserDefaults.standard.set(self.themedCheck, forKey: "ThemeChecked")
            self.themeColor = "card3"
          }
        }
      }
    }
  }
}
struct themes: Identifiable {
  var id = UUID()
  var name: String
  var color: String
}
let themeData = [
  themes(name: "Default", color: "card3"),
  themes(name: "Theme 1", color: "Theme1"),
  themes(name: "Theme 2", color: "Theme2")
]


Here’s a simple checkbox view that hopefully you can apply to your ThemesView
Code Block Swift
struct Themes: View {
var body: some View {
List {
ForEach(themeData) { themedata in
Checkbox(index: themeData.firstIndex(of: themedata)!)
}
.padding()
}
}
}
struct Checkbox: View {
@AppStorage("themeChecked") private var themeChecked = 0 // since you want it stored in UserDefaults
let index: Int
var isChecked: Bool { index == themeChecked }
var body: some View {
Label(isChecked ? "Checked" : "Unchecked", systemImage: isChecked ? "checkmark.circle" : "circle")
.onTapGesture { themeChecked = index }
}
}

You can pass in the themes variable to the checkbox and add the other styling to the view as well.
Allowing only one box to be checked
 
 
Q