[ad_1]
Right here is an easy record view of “Matter” struct gadgets. The objective is to current an editor view when a row of the record is tapped. On this code, tapping a row is predicted to trigger the chosen matter to be saved as “tappedTopic” in an @State var and units a Boolean @State var that causes the EditorV to be introduced.
When the code as proven is run and a line is tapped, its matter title prints correctly within the Print assertion within the Button motion, however then the app crashes as a result of self.tappedTopic! finds tappedTopic to be nil within the EditTopicV(…) line.
If the road “tlVM.objectWillChange.ship()” is uncommented, the code runs superb. Why is that this wanted?
And a second puzzle: within the case the place the code runs superb, with the objectWillChange.ship() uncommented, a print assertion within the EditTopicV init() exhibits that it runs twice. Why?
Any assist could be vastly appreciated. I’m utilizing Xcode 13.2.1 and my deployment goal is ready to iOS 15.1.
Matter.swift:
struct Matter: Identifiable {
var title: String = "Default"
var iconName: String = "circle"
var id: String { title }
}
TopicListV.swift:
struct TopicListV: View {
@ObservedObject var tlVM: TopicListVM
@State var tappedTopic: Matter? = nil
@State var doEditTappedTopic = false
var physique: some View {
VStack(alignment: .main) {
Checklist {
ForEach(tlVM.matters) { matter in
Button(motion: {
tappedTopic = matter
// why is the next line wanted?
tlVM.objectWillChange.ship()
doEditTappedTopic = true
print("Tapped matter = (tappedTopic!.title)")
}) {
Label(matter.title, systemImage: matter.iconName)
.padding(10)
}
}
}
Spacer()
}
.sheet(isPresented: $doEditTappedTopic) {
EditTopicV(tlVM: tlVM, originalTopic: self.tappedTopic!)
}
}
}
EditTopicV.swift (Editor View):
struct EditTopicV: View {
@ObservedObject var tlVM: TopicListVM
@Atmosphere(.presentationMode) var presentationMode
let originalTopic: Matter
@State non-public var editTopic: Matter
@State non-public var ic = "circle"
let iconList = ["circle", "leaf", "photo"]
init(tlVM: TopicListVM, originalTopic: Matter) {
print("DBG: EditTopicV: originalTopic = (originalTopic)")
self.tlVM = tlVM
self.originalTopic = originalTopic
self._editTopic = .init(initialValue: originalTopic)
}
var physique: some View {
VStack(alignment: .main) {
HStack {
Button("Cancel") {
presentationMode.wrappedValue.dismiss()
}
Spacer()
Button("Save") {
editTopic.iconName = editTopic.iconName.lowercased()
tlVM.change(matter: originalTopic, to: editTopic)
presentationMode.wrappedValue.dismiss()
}
}
HStack {
Textual content("Identify:")
TextField("title", textual content: $editTopic.title)
Spacer()
}
Picker("Coloration Theme", choice: $editTopic.iconName) {
ForEach(iconList, id: .self) { icon in
Textual content(icon).tag(icon)
}
}
.pickerStyle(.segmented)
Spacer()
}
.padding()
}
}
TopicListVM.swift (Observable Object View Mannequin):
class TopicListVM: ObservableObject {
@Revealed var matters = [Topic]()
func append(matter: Matter) {
matters.append(matter)
}
func change(matter: Matter, to newTopic: Matter) {
if let index = matters.firstIndex(the place: { $0.title == matter.title }) {
matters[index] = newTopic
}
}
static func ex1() -> TopicListVM {
let tvm = TopicListVM()
tvm.append(matter: Matter(title: "leaves", iconName: "leaf"))
tvm.append(matter: Matter(title: "images", iconName: "picture"))
tvm.append(matter: Matter(title: "shapes", iconName: "circle"))
return tvm
}
}
Here is what the record appears to be like like:
[ad_2]

