Передача списка между представлениями в SwiftUi
Я делаю приложение со списком ToDo самостоятельно, чтобы попытаться познакомиться с разработкой для iOS, и у меня возникла одна проблема:
У меня есть отдельный
View
связана для входа в новую задачу с. Вот код этого файла:
import SwiftUI
struct AddTask: View {
@State public var task : String = ""
@State var isUrgent: Bool = false // this is irrelevant to this problem you can ignore it
var body: some View {
VStack {
VStack(alignment: .leading) {
Text("Add New Task")
.bold()
.font(/*@START_MENU_TOKEN@*/.title/*@END_MENU_TOKEN@*/)
TextField("New Task...", text: $task)
Toggle("Urgent", isOn: $isUrgent)
.padding(.vertical)
Button("Add task", action: {"call some function here to get what is
in the text field and pass back the taskList array in the Content View"})
}.padding()
Spacer()
}
}
}
struct AddTask_Previews: PreviewProvider {
static var previews: some View {
AddTask()
}
}
Итак, что мне нужно взять введенную переменную задачи и вставить ее в массив, который будет отображаться в списке в моем основном файле.
Вот файл для справки:
import SwiftUI
struct ContentView: View {
@State var taskList = ["go to the bakery"]
struct AddButton<Destination : View>: View {
var destination: Destination
var body: some View {
NavigationLink(destination: self.destination) { Image(systemName: "plus") }
}
}
var body: some View {
VStack {
NavigationView {
List {
ForEach(self.taskList, id: \.self) {
item in Text(item)
}
}.navigationTitle("Tasks")
.navigationBarItems(trailing: HStack { AddButton(destination: AddTask())})
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
}
Мне нужна функция для выполнения задачи, введенной в
TextField
, и передать его обратно в массив в
ContentView
для отображения в
List
для пользователя
-Спасибо за помощь
2 ответа
Вы можете добавить свойство закрытия в свой обратный вызов, когда пользователь нажимает
Add Task
. Именно так:
struct AddTask: View {
var onAddTask: (String) -> Void // <-- HERE
@State public var task: String = ""
@State var isUrgent: Bool = false
var body: some View {
VStack {
VStack(alignment: .leading) {
Text("Add New Task")
.bold()
.font(.title)
TextField("New Task...", text: $task)
Toggle("Urgent", isOn: $isUrgent)
.padding(.vertical)
Button("Add task", action: {
onAddTask(task)
})
}.padding()
Spacer()
}
}
}
Затем в
ContentView
:
.navigationBarItems(
trailing: HStack {
AddButton(
destination: AddTask { task in
taskList.append(task)
}
)
}
)
jn_pdx предоставляет хорошее решение, передавая
Binding
taskList в. Но я думаю
AddTask
используется для добавления новой задачи, поэтому он должен фокусироваться только на новой задаче, а не на полном списке задач.
Вы можете использовать
@Binding
для передачи ссылки из родительского представления в дочернее представление, которое может быть изменено дочерним элементом. См. Приложенный код и найдите
<-- Here
линий.
struct ContentView: View {
@State var taskList = ["go to the bakery"]
struct AddButton<Destination : View>: View {
var destination: Destination
var body: some View {
NavigationLink(destination: self.destination) { Image(systemName: "plus") }
}
}
var body: some View {
VStack {
NavigationView {
List {
ForEach(self.taskList, id: \.self) {
item in Text(item)
}
}.navigationTitle("Tasks")
.navigationBarItems(trailing: HStack { AddButton(destination: AddTask(taskList: $taskList))}) //<-- Here
}
}
}
}
struct AddTask: View {
@Binding var taskList : [String] //<-- Here
@State private var task : String = ""
@State private var isUrgent: Bool = false // this is irrelevant to this problem you can ignore it
@Environment(\.presentationMode) private var presentationMode
var body: some View {
VStack {
VStack(alignment: .leading) {
Text("Add New Task")
.bold()
.font(.title)
TextField("New Task...", text: $task)
Toggle("Urgent", isOn: $isUrgent)
.padding(.vertical)
Button("Add task", action: {
taskList.append(task) //<-- Here
presentationMode.wrappedValue.dismiss()
})
}.padding()
Spacer()
}
}
}
struct AddTask_Previews: PreviewProvider {
static var previews: some View {
AddTask(taskList: .constant([])) //<-- Here
}
}
Я также использовал
presentationMode
чтобы закрыть дочернее представление после добавления нового элемента - это, конечно, необязательно и может быть удалено, если вы не хотите такого поведения.