简体   繁体   English

SwiftUI 保存新的 Object 并导航到它

[英]SwiftUI Save New Object and Navigate to it

When the NavigationLink is pressed I want to create an object (with the time when it was pressed), add it to the savedObjects and pass then new object to the destination view.当 NavigationLink 被按下时,我想创建一个 object(以及按下它的时间),将其添加到savedObjects然后将新的 object 传递给目标视图。 How can I do this without changing the state while the view is updating?在视图更新时如何在不更改 state 的情况下执行此操作?

struct ContentView: View {

    @State private var savedObjects = [
        MyObject(
            id: 0,
            date: Date()
        ),
        MyObject(
            id: 1,
            date: Date()
        ),
        MyObject(
            id: 2,
            date: Date()
        ),
        MyObject(
            id: 3,
            date: Date()
        )
    ]

    var body: some View {
        NavigationView {
            List {
                NavigationLink("Save new object and navigate to it", destination: DestinationView(object: MyObject(id: Int.random(in: 10...1000), date: Date())))
                ForEach(savedObjects) { object in
                    NavigationLink("Navigate to object \(object.id)", destination: DestinationView(object: object))
                }
            }
        }
    }
}

class MyObject: ObservableObject, Identifiable {
    var id: Int
    var date: Date

    init(id: Int, date: Date) {
        self.id = id
        self.date = date
    }
}

struct DestinationView: View {

    @ObservedObject var object: MyObject

    var body: some View {
        VStack {
            Text("object \(object.id)")
            Text("date: \(object.date.description)")
        }
    }
}

Here is a solution that refreshes state with a new Date when the link appears.这是一个解决方案,当链接出现时,用新的日期刷新 state。

struct LinkWithPayloadView: View {
    @State private var date = Date()
    
    var body: some View {
        NavigationView {
            navigationLink(payload: "Cookies and Milk", date: date)
                .onAppear(perform: {
                    date = Date()
                })
        }
    }
    
    func navigationLink(payload: String, date: Date) -> some View {
        let formatter = DateFormatter()
        formatter.dateFormat = "HH:mm:ss"
        let payload = Payload(timestamp: date, inners: payload)

        let vstack = VStack {
            Text("\(payload.inners)")
            Text("\(formatter.string(from: payload.timestamp))")
        }

        return NavigationLink(payload.inners, destination: vstack)
    }
    
    struct Payload {
        let timestamp : Date
        let inners : String
    }
}

Credit @mallow for the idea 这个想法归功于@mallow

My question is why can't you make a separate destination view to save the object?我的问题是为什么不能制作单独的目标视图来保存 object? Then you don't need to worry about saving it in the starting view.然后您不必担心将其保存在起始视图中。

struct DestinationView: View {
@Environment(\.managedObjectContext) var managedObjectContext
@ObservedObject var object: MyObject

init(id : Int, date : Date) {
    let myObject = MyObject(context: managedObjectContext)
    myObject.date = date
    myObject.id = id
    try! managedObjectContext.save()
    self.object = myObject
}

var body: some View {
    VStack {
        Text("object \(object.id)")
        Text("date: \(object.date.description)")
    }
}
}

Then you can just reload the objects from coredata when the navigation closes.然后,您可以在导航关闭时从 coredata 重新加载对象。

I think programmatic navigation is the best solution in my case.我认为程序化导航是我的最佳解决方案。 So clicking a different button that creates and saves the object which in turn creates a new NavigationLink and then initiating the navigation immediately as explained here: https://www.hackingwithswift.com/quick-start/swiftui/how-to-use-programmatic-navigation-in-swiftui因此,单击创建并保存 object 的其他按钮,该按钮又创建一个新的 NavigationLink,然后立即启动导航,如下所述: https://www.hackingwithswift.com/quick-start/swiftui/how-to-use- swiftui中的程序化导航

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM