SwiftUI:NavigationLink 在变量更新时弹出
Posted
技术标签:
【中文标题】SwiftUI:NavigationLink 在变量更新时弹出【英文标题】:SwiftUI: NavigationLink pops back when variable is updated 【发布时间】:2022-01-14 08:53:00 【问题描述】:我遇到了一个问题,即更新变量时导航链接会弹出。这有点令人困惑,因为这种行为不会发生在应用程序的其他地方,但我正在做同样的事情。
首先,有一个符合 Identifiable 的 Vehicle 结构体。在内容视图中,它显示在滚动视图中的 NavigationView 中。
ScrollView(showsIndicators: false)
VStack
ForEach(user.vehicles) vehicle in
VehicleListItem(user: $user,
vehicle: vehicle)
该列表项有一个导航链接,可将用户带到不同的视图。 Vehicle 作为绑定传递给下一个视图。
NavigationLink(destination:
VehicleView(user: $user,
vehicle: $user.vehicles[user.vehicles.firstIndex(where: $0.id == vehicle.id)!],
make: vehicle.make,
model: vehicle.model,
year: vehicle.year
)
, label:
Image(systemName: "car")
.font(.system(size: 100))
).padding(.bottom, 20)
在车辆视图中,用户可以编辑车辆信息(品牌、型号、年份),并且工作正常。当用户对 Vehicle 进行更改时,它不会弹回之前的视图。
Section()
VehicleHandler(make: $make, model: $model, year: $year)
Button(action:
//Update
vehicle.make = make
vehicle.model = model
vehicle.year = year
, label:
ButtonView(label: "Update")
).disabled(make.isEmpty ||
model.isEmpty ||
(make == vehicle.make && model == vehicle.model && year == vehicle.year))
车辆处理程序
struct VehicleHandler: View
enum Field: Hashable
case make
case model
@FocusState private var field: Field?
@Binding var make: String
@Binding var model: String
@Binding var year: Int //Set to current year
var body: some View
TextField("Make", text: $make)
.submitLabel(.next)
.focused($field, equals: .make)
.onSubmit
field = .model
TextField("Model", text: $model)
.submitLabel(.done)
.focused($field, equals: .model)
Picker("Year", selection: $year, content:
ForEach((1900...Date().year()).reversed(), id: \.self) year in
Text(String(year))
.tag(year as Int)
)
现在,用户可以添加维护记录。一旦他们添加了一条记录,它就会使用 ForEach 显示。记录也符合可识别性。
//Only show 5
ForEach(vehicle.maintenanceRecords.prefix(5)) record in
NavigationLink(destination:
MaintenanceView(user: $user,
record: $vehicle.maintenanceRecords[vehicle.getMaintenanceIndex(id: record.id)],
date: record.date,
mileage: record.mileage ?? 0,
note: record.note,
cost: record.cost ?? 0,
tasks: record.tasks)
, label:
Text("\(record.date.formattedNoYear()) - \(record.note)")
)
同样的概念被用于编辑维护记录。记录作为绑定传递,记录信息被传递以更新各个字段。当用户按下更新时,它会更新记录。此时,只要您进行编辑并按更新,它就会弹回 VehicleView。当我不使用 ID 时,我曾经遇到过这个问题,但是,每个结构都符合 Identifiable 并且 ID 没有被修改。我已经检查以确保它们保持不变,其中包括车辆的 ID 和记录。有谁知道为什么它会一直出现在这里,但是当车辆信息更新时却没有?如果您需要更多信息,请告诉我。
RecordHandler(user: $user,
date: $date,
mileage: $mileage,
note: $note,
cost: $cost,
task: $task,
tasks: $tasks)
Section()
Button(action:
//Update record
record.date = date
record.note = note
record.tasks = tasks
if mileage.isZero == false
record.mileage = mileage
if cost.isZero == false
record.cost = cost
//Clear task
task = ""
, label:
ButtonView(label: "Update")
).disabled(note.isEmpty ||
(date == record.date && mileage == record.mileage && note == record.note && cost == record.cost && tasks == record.tasks)
)
记录处理程序
struct RecordHandler: View
enum Field: Hashable
case note
case mileage
case cost
case task
@FocusState var field: Field?
@Binding var user: User
@Binding var date: Date
@Binding var mileage: Float
@Binding var note: String
@Binding var cost: Float
@Binding var task: String
@Binding var tasks: [Vehicle.Record.Task]
@State var suggestion: String = ""
var body: some View
Section()
DatePicker("Date", selection: $date)
TextField("Note", text: $note)
.submitLabel(.next)
.focused($field, equals: .note)
.onSubmit
field = .mileage
FieldWithLabel(label: "Mileage", value: $mileage, formatter: NumberFormatter.number)
.submitLabel(.next)
.focused($field, equals: .mileage)
.onSubmit
field = .cost
FieldWithLabel(label: "Cost", value: $cost, formatter: NumberFormatter.currency)
.submitLabel(.next)
.focused($field, equals: .cost)
.onSubmit
field = .task
//For task
Section()
HStack
TextField("Task", text: $task)
.submitLabel(.done)
.focused($field, equals: .task)
.onSubmit
addTask()
field = .task
.toolbar(content:
ToolbarItemGroup(placement: .keyboard)
Spacer()
Button("Close")
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
)
.onChange(of: task, perform: value in
//See if any of the saved task are similar
if user.tasks.contains(where: $0.contains(value))
//Set suggestion
suggestion = user.tasks.first(where: $0.contains(value))!
else
//Leave it empty if there's nothing
suggestion = ""
)
Spacer()
Button(action:
addTask()
, label:
Image(systemName: "plus.circle.fill")
.font(.system(size: 22))
).buttonStyle(BorderlessButtonStyle())
//To show task suggestions
if suggestion.isEmpty == false
Button(action:
//Set task to suggestion
task = suggestion
//Add task
addTask()
//Focus field
field = .task
, label:
HStack
Text("Suggestion")
Spacer()
Text(suggestion)
)
ForEach(tasks) task in
Text(task.name)
.onDelete(perform: delete)
func addTask()
//Create
let task = Vehicle.Record.Task(name: task)
//Add to array
tasks.append(task)
//Clear
self.task = ""
func delete(at offsets: IndexSet)
tasks.remove(atOffsets: offsets)
【问题讨论】:
欢迎来到 SO - 请使用 tour 并阅读 How to Ask 以改进、编辑和格式化您的问题。如果没有Minimal Reproducible Example,就无法帮助您进行故障排除。 【参考方案1】:我遇到了同样的问题,今天设法解决了。尝试将选项 .navigationViewStyle(.stack)
添加到您的 NavigationView
struct ContentView: View
var body: some View
NavigationView
//All your content and navigation links
.navigationViewStyle(.stack)
【讨论】:
所以我将其设置为,但是,我将其应用于导航视图内的列表而不是导航视图本身。一旦我移动它,它就开始工作了。 对我来说,将内容包装在NavigationView
中解决了它。谢谢你的提示。不需要.navigationViewStyle(.stack)
。以上是关于SwiftUI:NavigationLink 在变量更新时弹出的主要内容,如果未能解决你的问题,请参考以下文章
SwiftUI 上的 NavigationLink 两次推送视图
SwiftUI:NavigationLink 内的水平 ScrollView 会中断导航
有没有办法向 NavigationLink 添加额外的功能? SwiftUI