如何解决在 swiftui 中编辑现有数组时的持久数据
我想弄清楚如何让两件事一起工作。第一个是使用 userdefaults 的持久数据,我通过使用 @Published 和 @Observable 发现了这一点,然后使用 JSONencoder/decoder 来保存数据,即使应用程序关闭并重新打开也是如此。我最近也通过上一个问题了解到的第二个 https://stackoverflow.com/questions/62106227/best-way-to-update-edit-an-array-element-in-swiftui/67752060#67752060>
我的问题是将两者结合起来。我似乎无法弄清楚如何使用预定义的数据数组获取以下代码并使用 UserDefaults 使更改保持不变。任何帮助将不胜感激。也许我的处理方式有误。
通过 UserDefaults 持久化数据的代码
import SwiftUI
struct CharacterModel: Identifiable,Codable {
var id = UUID()
var name: String
var level: Int
}
class CharacterViewModel: ObservableObject {
@Published var characters = [CharacterModel]() {
// Write data back to Model
didSet {
let encoder = JSONEncoder()
if let encoded = try?
encoder.encode(characters) {
UserDefaults.standard.set(encoded,forKey: "Characters")
}
}
}
init() {
if let characters = UserDefaults.standard.data(forKey: "Characters") {
let decoder = JSONDecoder()
if let decoded = try?
decoder.decode([CharacterModel].self,from: characters) {
self.characters = decoded
return
}
}
self.characters = []
}
}
struct DetailView: View {
@Environment(\.presentationMode) var presentationMode
@ObservedObject var characterVM: CharacterViewModel
@State private var name = ""
@State private var level = ""
var body: some View {
NavigationView {
Form {
TextField("Name",text: $name)
TextField("Level",text: $level)
.keyboardType(.numberPad)
}
.navigationBarTitle("Add Level")
.navigationBarItems(trailing: Button("Save") {
if let actualLevel = Int(self.level) {
let character = CharacterModel(name: self.name,level: actualLevel)
self.characterVM.characters.append(character)
self.presentationMode.wrappedValue.dismiss()
}
})
}
}
}
struct DetailView_Previews: PreviewProvider {
static var previews: some View {
DetailView(characterVM: CharacterViewModel())
}
}
struct Home: View {
@State private var showingAddCharacter = false
@State var selectedCharacter : CharacterModel!
@ObservedObject var characterVM = CharacterViewModel()
var body: some View {
NavigationView {
List {
ForEach(characterVM.characters) { char in
HStack {
VStack(alignment: .leading) {
Text(char.name)
.font(.headline)
}
Spacer()
Text("\(char.level)")
}
}
.onDelete(perform: removeItems)
}
.navigationBarTitle("Characters")
.navigationBarItems(trailing:
Button(action: {
self.showingAddCharacter = true
}) {
Image(systemName: "plus")
}
)
.sheet(isPresented: $showingAddCharacter) {
DetailView(characterVM: self.characterVM)
}
}
}
func removeItems(at offsets: IndexSet) {
characterVM.characters.remove(atOffsets: offsets)
}
}
struct Home_Previews: PreviewProvider {
static var previews: some View {
Home()
}
}
编辑预定义数组
class Training: ObservableObject,Identifiable {
let id: String
@Published var trainingName: String
@Published var isRequired: Bool
init(id: String,trainingName: String,isRequired: Bool) {
self.id = id
self.trainingName = trainingName
self.isRequired = isRequired
}
}
class GetTrainings: ObservableObject {
@Published var items = [Training]()
init() {
self.items = [
Training(id: "ttt1",trainingName: "Safety",isRequired: true),Training(id: "ttt2",trainingName: "Administrative",isRequired: false),Training(id: "ttt3",trainingName: "Computer",Training(id: "ttt4",trainingName: "People",Training(id: "ttt5",trainingName: "Managerial",]
}
}
struct TrainingList: View {
@ObservedObject var trainings = GetTrainings()
var body: some View {
NavigationView {
VStack {
List {
ForEach(trainings.items) { training in
HStack {
NavigationLink(destination: TrainingView(training: training)) {
Text("\(training.trainingName)")
}
}
}
}
}.navigationBarTitle("Training List")
.onAppear {
self.trainings.objectWillChange.send() // refresh
}
}
}
}
struct TrainingView: View {
@ObservedObject var training: Training
var body: some View {
VStack {
Text("\(training.trainingName)").font(.body)
Text("\(training.isRequired == true ? "Required Training" : "Training Not Required")")
HStack {
NavigationLink(destination: EditTraining(training: training)) {
Text("Edit Training Details")
}
}
}.navigationBarTitle("\(training.trainingName) Page",displayMode: .inline)
}
}
struct EditTraining: View {
@ObservedObject var training: Training
@State private var newName: String
@State private var isRequiredTraining: Bool
init(training: Training) {
self.training = training
self._newName = State(initialValue: training.trainingName)
self._isRequiredTraining = State(initialValue: training.isRequired)
}
private func submitData() {
let newName = self.newName
let newBoolVal = self.isRequiredTraining
print("Firebase Sync Id is :\(training.id) Text: \(newName) and Bool: \(newBoolVal)")
self.training.trainingName = newName
self.training.isRequired = newBoolVal
}
var body: some View {
VStack {
Form {
Section (header: Text("Edit")) {
Text("\(training.trainingName)")
/* TextField should Populate With passed In Training Name Here*/
TextField("New Name",text: self.$newName)
Toggle(isOn: self.$isRequiredTraining) {
Text("Is Required")
}
}
Section {
Button(action: {
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder),to:nil,from:nil,for:nil)
self.submitData()
}) {
Text("Submit")
}
}
}
}.navigationBarTitle("Edit Training Page",displayMode: .inline)
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。