I do not declare a new State var but an AppStorage…
Maybe the State var is to know you have saved and then disable Save Button.
Declare this:
@AppStorage("Names") var storedNames: String = ""
Then, in the Save, we concatenate all the names.
Note: AppStorage saves in UserDefaults. But it cannot save directly and array, so we transform the array of String into a String, by concatenation.
In Load, we de concatenate.
You will see how fun on arrays, as reduce, split and map are really powerful here.
If you don't know them, learn by reading documentation. It is really important to understand how they work
So the complete code:
struct ContentView: View {
@State private var names: [String] = []
@State private var nameToAdd = ""
@State private var pickedName = ""
@State private var shouldRemovePickedName = false
@AppStorage("Names") var storedNames: String = "" // The concatenation of all the names, separated by commas
var body: some View {
VStack {
VStack(spacing: 8) {
Image(systemName: "person.3.sequence.fill")
.foregroundStyle(.tint)
.symbolRenderingMode(.hierarchical)
Text("Pick-a-Pal")
}
.font(.title)
.bold()
//3項条件演算子
Text(pickedName.isEmpty ? "" : pickedName)
.font(.title2)
.bold()
.foregroundStyle(.tint)
List {
ForEach(names, id: \.self) { name in
Text(name)
}
}
.clipShape(RoundedRectangle(cornerRadius: 8))
TextField("Add Name", text: $nameToAdd)
//単語の自動修正をオフにする
.autocorrectionDisabled()
.onSubmit {
if !nameToAdd.isEmpty {
if names.contains(nameToAdd) {
// You could add an alert, or sound a beep if already exists
} else {
names.append(nameToAdd)
}
nameToAdd = ""
}
}
Divider()
Toggle("Remove when picked", isOn: $shouldRemovePickedName)
Button {
if let randomName = names.randomElement() {
pickedName = randomName
if shouldRemovePickedName {
names.removeAll() { name in
return (name == randomName)
}
}
} else {
pickedName = ""
}
} label: {
Text("Pick Random Name")
.padding(.vertical, 8)
.padding(.horizontal, 16)
}
.buttonStyle(.borderedProminent)
.font(.title2)
Divider()
HStack { // Show 2 buttons on HStack
Button {
// We concatenate the names ; reduce func is useful for this
storedNames = names.reduce("", { $0 + $1 + "," }) // Comma to separate next name
// A more readable equivalent is:
// storedNames = names.reduce("", { concatenate, name in concatenate + name + "," })
print(storedNames)
} label: {
Text("Save Names")
}
Spacer(minLength: 40)
Button {
// We need to de-concatenate: split function splits the elements in a string into an array, dividing by the separator
names = storedNames.split(separator: ",").map( { String($0) }) // as split returns an array of subtrings, we need to map into String
print(names) // To see what we get
} label: {
Text("Load saved Names")
}
}
}
.padding()
}
}