На основании этой похвалы от @ nine-stone (спасибо!) Я реализовал более SwiftUI-способ, поэтому решил свою проблему. Он не позволяет настраивать элементы навигации, как я планировал, но это была не та проблема, которую нужно было решить. Я хотел использовать представление Child
в навигационной ссылке, а также внутри модального листа. Проблема заключалась в том, как выполнить пользовательские действия отмены. Вот почему я удалил реализацию кнопки и заменил ее закрытием cancelAction
. Теперь я могу отображать дочерний вид где угодно и как угодно.
Одна вещь, которую я до сих пор не знаю, почему SwiftUI не применяет дочерний контекст к кнопке внутри метода saveButton
.
Тем не менее, вот код, может быть, он помогает кому-то в будущее.
import SwiftUI
import PlaygroundSupport
struct ContentView: View {
@Environment(\.presentationMode) var presentationMode
var body: some View {
NavigationView {
NavigationLink(
destination: Child(
// Instead of defining the buttons here, I send an optional
// cancel action to the child. This will make it possible
// to use the child view on navigation links, as well as in
// modal dialogs.
cancelAction: {
self.presentationMode.wrappedValue.dismiss()
}
)
) {
Text("Open")
}
}
}
}
struct Child: View {
// Store the value from the textfield
@State private var value = "default"
@Environment(\.presentationMode) var presentationMode
var cancelAction: (() -> Void)?
// Make this button available inside this view, and inside the parent view.
// This makes sure the visibility of this button is always the same.
var saveButton: some View {
Button(action: save) {
Text("Save")
}
}
var body: some View {
VStack {
// Simple textfield to allow a string to change.
TextField("Value", text: $value)
// Just for the playground to change the value easily.
// Usually it would be chnaged through the keyboard input.
Button(action: {
self.value = "new value"
}) {
Text("Update")
}
}
.navigationBarItems(
leading: self.cancelAction != nil ? Button(action: self.cancelAction!, label: {
Text("Cancel")
}) : nil,
trailing: self.saveButton
)
}
func save() {
// This always displays the default value of the state variable.
// Even after the Update button was used and the value did change inside
// the textfield.
print("\(value)")
}
}
PlaygroundPage.current.setLiveView(ContentView())