考虑代码
@EnvironmentObject var navModel: NavigationModel
var body: some View {
someView
.navigationDestination(for: ImageModel.self) { imageModel in
ImageDetailedView(image: imageModel)
.environmentObject(navModel) //this is required
}
}
导航不被认为是视图的子对象吗?如果是这样,在导航堆栈周围不断抛出environemntObjects是正常的吗?
import Combine
import SwiftUI
enum Destination {
case firstPage
case secondPage
}
enum Category: Int, Hashable, CaseIterable, Identifiable, Codable {
case dessert
case pancake
case salad
case sandwich
var id: Int { rawValue }
var localizedName: LocalizedStringKey {
switch self {
case .dessert:
return "Dessert"
case .pancake:
return "Pancake"
case .salad:
return "Salad"
case .sandwich:
return "Sandwich"
}
}
}
@available(iOS 16.0, *)
class Coordinator3: ObservableObject {
@Published var path = NavigationPath()
func gotoHomePage() {
path.removeLast(path.count)
}
func tapOnEnter() {
path.append(Destination.firstPage)
}
func tapOnFirstPage() {
path.append(Destination.secondPage)
}
func tapOnSecondPage() {
path.removeLast()
}
func test() {
path.removeLast(path.count)
path.append(2)
}
}
class Test :ObservableObject {
var name = "test"
}
@available(iOS 16.0, *)
struct SplitTestView: View {
@State var selectedCategory: Category?
var categories = Category.allCases
@ObservedObject var coordinator = Coordinator3()
@StateObject var test = Test()
var body: some View {
NavigationSplitView {
List(categories, selection: $selectedCategory) { category in
NavigationLink(category.localizedName, value: category)
}
} detail: {
NavigationStack(path: $coordinator.path) {
switch selectedCategory {
case .dessert:
Text(selectedCategory!.localizedName)
case .pancake:
VStack {
Text("Navigation stack")
.padding()
NavigationLink("NavigationLink to enter first page", value: Destination.firstPage)
.padding()
NavigationLink("NavigationLink to enter second page", value: Destination.secondPage)
.padding()
}
.navigationDestination(for: Destination.self) { destination in
if destination == .firstPage {
FirstPage()
} else {
Text(
"SecondPage()"
)
}
}
case .salad: Text(selectedCategory!.localizedName)
case .sandwich: Text(selectedCategory!.localizedName)
case .none: Text("hi")
}
}.environmentObject(test)
}
}
}
@available(iOS 16.0, *)
struct SplitTestView_Previews: PreviewProvider {
static var previews: some View {
SplitTestView()
}
}
struct FirstPage: View {
@EnvironmentObject var test: Test
var body: some View {
Text("First Page \(test.name)")
}
}
3条答案
按热度按时间r7knjye21#
这就是为什么MRE很重要,这就是为什么我在第一条评论中提到它,你介绍了
NavigationSplitView
。如果使用
NavigationSplitView
,则必须将EnvironmentObject
注入到NavigationSplitView
。如果只使用
NavigationStack
,则必须在NavigationStack
上注入只需将注入代码向下移动一行。
在迁移指南中,苹果谈到了这两种类型之间的差异。
https://developer.apple.com/documentation/swiftui/migrating-to-new-navigation-types
他们将
NavigationStack
的内部称为“内容”以及
NavigationSplitView
“列”的内部在它们各自的设置中,“列”和“内容”仅分别与
NavigationLink
s/navigationDestination
共享NavigationSplitView
或NavigationStack
。在
NavigationSplitView
内部的NavigationLink
在其自己的列中呈现。注入应该始终发生在最上面的共享
View
。blpfk2vs2#
environmentObjects不通过导航系统是一个已知的行为。你必须每次都手动注入。
在WWDC的休息室里,有人问:
当我将环境对象传递给工作表或NavigationLink时,我遇到过几次环境对象为nil的间歇性崩溃。
答案是:
NavigationLink的设计并没有将EnvironmentObject传递到它的目的地,因为不清楚应该从哪里继承environmentObject。我怀疑这可能是导致你的问题的原因。为了获得你期望的行为,你必须在那个时候显式地传递environmentObject。
https://developer.apple.com/forums/thread/683564
63lcw9qa3#
我发现当我的项目变得越来越复杂时,使用EnvironmentObjects会有一些bug。
要做到这一点,在你的类中,列出一个属性
static let shared = NavigationModel()
。然后,在任何你想使用这个类的视图中,在视图属性中引用它作为@ObservedObject var navModel = NavigationModel.shared
。这种方法有利有弊,但我发现利大于弊,因为环境对象往往是错误的。