画面遷移したらリストが消える
Q&A
Swift初心者です
初めての開発、質問なので見にくかったらすいません
Playgroundsを参考に在庫管理アプリを作ろうとしています。
発生している問題・エラー
このお風呂というリストをクリックすると、 この画面になるようになっています2枚目の画像の右上プラスボタンを押すとリストを追加できるのですが、
左上の<を押して1枚目の画面に戻ると追加したリストが消えます
何となくどの箇所が原因なのかは分かるのですが、解決の仕方が分かりません
原因と思われる箇所
EventViewでItemViewを表示させるときのItemDataのBinding
ItemView(itemData: ItemData(), event: eventBinding)
どうしたらいいか分からないので下に書いたコード全部載っけてます、、
Event
import SwiftUI
struct Event: Identifiable, Hashable, Codable {
var id = UUID()
var title = ""
static var delete = Event()
}
EventData
import SwiftUI
class EventData: ObservableObject {
@Published var events: [Event] = [
Event(
title: "お風呂"
),
]
func add(_ event: Event) {
events.append(event)
}
func remove(_ event: Event) {
events.removeAll { $0.id == event.id}
}
func getBindingToEvent(_ event: Event) -> Binding<Event>? {
Binding<Event>(
get: {
guard let index = self.events.firstIndex(where: { $0.id == event.id }) else { return Event.delete }
return self.events[index]
},
set: { event in
guard let index = self.events.firstIndex(where: { $0.id == event.id }) else { return }
self.events[index] = event
}
)
}
}
EventEditor
import SwiftUI
struct EventEditor: View {
@Binding var event: Event
var body: some View {
List {
TextField("New List", text: $event.title)
.font(.title2)
}
}
}
EventRow
import SwiftUI
struct EventRow: View {
@ScaledMetric var imageWidth: CGFloat = 40
let event: Event
var body: some View {
VStack {
Label {
Text(event.title)
} icon: {
Image(systemName: "pencil.circle")
}
}
}
}
EventView
import SwiftUI
struct EventView: View {
@ObservedObject var eventData: EventData
@State private var isAddingNewEvent = false
@State private var isEventEditor = false
@State private var newEvent = Event()
@State private var selection: Event?
var body: some View {
NavigationSplitView {
List(selection: $selection) {
ForEach(eventData.events) { event in
EventRow(event: event)
.tag(event)
.swipeActions {
Button(role: .destructive) {
selection = nil
eventData.remove(event)
} label: {
Label("Delete", systemImage: "trash")
}
}//swipe
}//ForEach
}//List
.toolbar {
ToolbarItem {
Button {
newEvent = Event()
isAddingNewEvent = true
} label: {
Image(systemName: "plus")
}
}
}
.sheet(isPresented: $isAddingNewEvent) {
NavigationStack {
EventEditor(event: $newEvent)
.toolbar {
ToolbarItem(placement: .cancellationAction) {
Button("Cancel") {
isAddingNewEvent = false
}
}
ToolbarItem {
Button {
eventData.add(newEvent)
isAddingNewEvent = false
} label: {
Text("Add" )
}
.disabled(newEvent.title.isEmpty)
}
}
}
}
} detail: {
ZStack {
if let event = selection, let eventBinding = eventData.getBindingToEvent(event) {
ItemView(itemData: ItemData(), event: eventBinding)
} else {
Text("Select an Event")
.foregroundStyle(.secondary)
}
}
}
}
}
Item
import SwiftUI
struct Item: Identifiable, Hashable, Codable {
var id = UUID()
var title = ""
var tasks = [Task(text: "", memo: "")]
var remainingTaskCount: Int {
tasks.filter { !$0.isCompleted && !$0.text.isEmpty }.count
}
var isComplete: Bool {
tasks.allSatisfy { $0.isCompleted || $0.text.isEmpty }
}
static var delete = Item()
}
struct NavigationBarBackButtonTextHidden: ViewModifier {
@Environment(\.presentationMode) var presentaion
func body(content: Content) -> some View {
content
.navigationBarBackButtonHidden(true)
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
Button(action: { presentaion.wrappedValue.dismiss() }) {
Image(systemName: "chevron.backward")
}
}
}
}
}
extension View {
func navigationBarBackButtonTextHidden() -> some View {
return self.modifier(NavigationBarBackButtonTextHidden())
}
}
ItemData
import SwiftUI
class ItemData: ObservableObject {
@Published var items: [Item] = [
Item(
title: "洗剤",
tasks: [Task(text: "マジックリン", memo: "¥305"),]
),
]
func add(_ item: Item) {
items.append(item)
}
func remove(_ item: Item) {
items.removeAll { $0.id == item.id}
}
func getBindingToItem(_ item: Item) -> Binding<Item>? {
Binding<Item>(
get: {
guard let index = self.items.firstIndex(where: { $0.id == item.id }) else { return Item.delete }
return self.items[index]
},
set: { item in
guard let index = self.items.firstIndex(where: { $0.id == item.id }) else { return }
self.items[index] = item
}
)
}
}
ItemEditor
import SwiftUI
struct ItemEditor: View {
@Binding var item: Item
var body: some View {
NavigationStack {
List {
TextField("New List", text: $item.title)
}
.navigationTitle("新規リスト")
.navigationBarTitleDisplayMode(.inline)
}
}//var
}//st
ItemRow
import SwiftUI
struct ItemRow: View {
@ScaledMetric var imageWidth: CGFloat = 40
let item: Item
var body: some View {
HStack {
Label {
VStack(alignment: .leading, spacing: 5) {
Text(item.title)
}
} icon: {
Image(systemName: "pencil.circle")
.padding(.trailing, 15)
}
if item.isComplete {
Spacer()
Image(systemName: "xmark.seal")
.foregroundStyle(.red)
}
}//H
.badge(item.remainingTaskCount)
}
}
ItemView
import SwiftUI
struct ItemView: View {
@ObservedObject var itemData: ItemData
@State private var selection: Item?
@State private var isShowTaskView = false
@State private var isShowEditorView = false
@State private var isShowEditor0 = false
@State private var newItem = Item()
@State private var isPickingSymbol = false
@Binding var event: Event
var body: some View {
NavigationStack {
List(selection: $selection) {
ForEach(itemData.items) { item in
ItemRow(item: item)
.onTapGesture {
selection = item
isShowTaskView = true
}
.swipeActions {
Button(role: .destructive) {
itemData.remove(item)
} label: {
Label("Delete", systemImage: "trash")
}
Button {
selection = item
isShowEditor0 = true
} label: {
Image(systemName: "pencil.tip.crop.circle.badge.plus")
}
}
} // ForEach
} // List
.sheet(isPresented: $isShowTaskView) {
NavigationStack {
VStack {
if let item = selection, let itemBinding = itemData.getBindingToItem(item) {
TaskView(item: itemBinding)
}
}.presentationDetents([.medium])
.toolbar {
Button {
isShowTaskView = false
} label: {
Text("OK")
}
}
}//navi
}
.sheet(isPresented: $isShowEditor0) {
NavigationStack {
VStack {
if let item = selection, let itemBinding = itemData.getBindingToItem(item) {
ItemEditor(item: itemBinding)
}
}
.toolbar {
Button {
isShowEditor0 = false
} label: {
Text("OK" )
}
}
}
}
.toolbar {
ToolbarItem {
Button {
newItem = Item()
isShowEditorView = true
} label: {
Image(systemName: "plus.square.on.square")
}
}
}//ItemViewのtoolbar
//右上のプラスボタン<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
.sheet(isPresented: $isShowEditorView) {
NavigationStack {
ItemEditor(item: $newItem)
.toolbar {
ToolbarItem {
Button {
itemData.add(newItem)
isShowEditorView = false
} label: {
Text("Add")
}
.disabled(newItem.title.isEmpty)
}
ToolbarItem(placement: .navigationBarLeading) {
Button {
isShowEditorView = false
} label: {
Text("Cancel")
}
}
}
}
}
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^右上のプラスボタン
}.navigationBarBackButtonTextHidden()
}//var
}//st
stock11App
import SwiftUI
@main
struct DatePlannerApp: App {
@StateObject private var eventData = EventData()
var body: some Scene {
WindowGroup {
EventView(eventData: eventData)
}
}
}
Task
import Foundation
struct Task: Identifiable, Hashable, Codable {
var id = UUID()
var text: String
var memo: String
var isCompleted = false
var date = Date.now
}
TaskRow
import SwiftUI
struct TaskRow: View {
@Binding var task: Task
var body: some View {
HStack {
Button {
task.isCompleted.toggle()
} label: {
Image(systemName: task.isCompleted ? "checkmark.circle.fill" : "circle")
}
.buttonStyle(.plain)
VStack {
TextField("Task Description", text: $task.text, axis: .vertical)
TextField("memo", text: $task.memo).font(.subheadline)
}
Spacer()
DatePicker("", selection: $task.date, displayedComponents: [.date])
.environment(\.locale, Locale(identifier: "ja_JP"))
}
}
}
TaskView
import SwiftUI
struct TaskView: View {
@Binding var item: Item
var body: some View {
NavigationStack {
List {
ForEach($item.tasks) { $task in
TaskRow(task: $task)
}
Button {
let newTask = Task(text: "", memo: "¥")
item.tasks.append(newTask)
} label: {
HStack {
Image(systemName: "plus")
Text("Add Task")
}
}//Button
}
}
}//var
}//st
宜くお願い致します。
0