swiftui - SwiftUI 视图未更新到环境对象
问题描述
当在 MenuView 中按下按钮时,我在让 ContentBodyView 正确更新时遇到问题。
当我打印出@Published currentPage 变量时,它会在按下按钮时发生变化,但似乎不会进入 ContentBodyView。我错过了什么吗?
我根据本教程编写了代码:https ://blckbirds.com/post/how-to-navigate-between-views-in-swiftui-by-using-an-environmentobject/
我尝试在 ContentBodyView 上执行 .onReceive 事件,但视图仍然没有改变。
应用程序.swift:
@main
struct App: App {
@StateObject var viewRouter = ViewRouter()
var body: some Scene {
WindowGroup {
ContentView().environmentObject(viewRouter)
}
}
}
内容视图:
struct ContentView: View {
// MARK: - PROPERTIES
// for future use...
@State var width = UIScreen.main.bounds.width - 90
// to hide view...
@State var x = -UIScreen.main.bounds.width + 90
@EnvironmentObject var viewRouter: ViewRouter
// MARK: - BODY
var body: some View {
VStack {
ZStack(alignment: Alignment(horizontal: .leading, vertical: .top)) {
ContentBodyView(x: $x)
.environmentObject(ViewRouter())
MenuView(x: $x)
.shadow(color: Color.black.opacity(x != 0 ? 0.1 : 0), radius: 5, x: 5, y: 0)
.offset(x: x)
.background(Color.black.opacity(x == 0 ? 0.5 : 0).ignoresSafeArea(.all, edges: .vertical).onTapGesture {
// hiding the view when back is pressed...
withAnimation {
x = -width
}
}) //: background
.environmentObject(ViewRouter())
} //: ZSTACK
// adding gesture or drag feature...
.gesture(DragGesture().onChanged({ (value) in
withAnimation {
if value.translation.width > 0 {
// disabling over drag...
if x < 0 {
x = -width + value.translation.width
}
} else {
if x != -width {
x = value.translation.width
}
}
}
}).onEnded({ (value) in
withAnimation {
// checking if half the value of menu is dragged means setting x to 0...
if -x < width / 2 {
x = 0
} else {
x = -width
}
}
})) //: GESTURE
} //: VSTACK
}
}
菜单视图:
struct MenuView: View {
// MARK: - PROPERTIES
var edges = UIApplication.shared.windows.first?.safeAreaInsets
// for future use...
@State var width = UIScreen.main.bounds.width - 90
// to hide view...
@Binding var x: CGFloat
@EnvironmentObject var viewRouter: ViewRouter
// MARK: - BODY
var body: some View {
HStack(spacing: 0) {
VStack(alignment: .leading) {
HStack{
Button(action: {
withAnimation {
x = -width
}
}) {
Image(systemName: "xmark")
.resizable()
.frame(width: 18, height: 18)
.padding()
.padding(.top, 25)
.foregroundColor(Color.black)
}
Spacer()
}
ForEach(menuData) { item in
Button(action: {
withAnimation {
if (item.router == "shareables") {
viewRouter.currentPage = .shareables
} else {
viewRouter.currentPage = .home
}
x = -width
}
}) {
Text("\(item.label)")
} //: BUTTON
} //: FOREACH
} //: VSTACK
.padding(.horizontal,20)
// since vertical edges are ignored....
.padding(.top,edges!.top == 0 ? 15 : edges?.top)
.padding(.bottom,edges!.bottom == 0 ? 15 : edges?.bottom)
// default width...
.frame(width: UIScreen.main.bounds.width - 90)
.background(Color.white)
.ignoresSafeArea(.all, edges: .vertical)
Spacer(minLength: 0)
} //: HSTACK
}
}
内容体视图:
struct ContentBodyView: View {
// MARK: - PROPERTIES
@EnvironmentObject var viewRouter: ViewRouter
@Binding var x : CGFloat
// MARK: - BODY
var body: some View{
VStack {
switch viewRouter.currentPage {
case .home:
NavigationBarView(x: $x, title: "Home")
Spacer()
HomeView()
.transition(.scale)
case .shareables:
NavigationBarView(x: $x, title: "Shareables")
Spacer()
ShareablesView()
.transition(.scale)
} //: SWITCH
} //: VSTACK
// for drag gesture...
.contentShape(Rectangle())
.background(Color.white)
}
}
视图路由器:
final class ViewRouter: ObservableObject {
@Published var currentPage: Page = .home
}
enum Page {
case home
case shareables
}
解决方案
ViewRouter
尝试在所有视图中使用相同的实例。
以下代码创建 的新实例ViewRouter
:
ContentBodyView(x: $x)
.environmentObject(ViewRouter())
MenuView(x: $x)
...
.environmentObject(ViewRouter())
将它们替换为:
@EnvironmentObject var viewRouter: ViewRouter
...
.environmentObject(viewRouter)
但实际上,每个环境通常只需要注入.environmentObject
一次,因此所有这些调用可能都是不必要的。
注入ViewRouter
一次ContentView
就足够了(如果您不使用sheet
等):
@StateObject var viewRouter = ViewRouter()
...
ContentView().environmentObject(viewRouter)
推荐阅读
- html - 从第一个搜索结果返回 URL
- javascript - 来自 ASP NET Web API 的 CORS 阻止 Ajax POST 调用 - 对预检请求的响应未通过访问控制检查
- performance - 浏览器中的内存使用如何处理图像 - 我可以做一个大精灵吗?
- numpy - 将数组与自身连接 n 次
- django - 尝试在 docker-machine cookiecutter-django 中运行 docker-compose 时出现“关系不存在”错误
- sql - 包含其他子集的 SQL 集问题
- php - 如何在实时服务器上执行 Laravel(电子邮件)作业
- javascript - 使用带有条件javascript的地图从数组中提取id
- python - 提供关键字参数后可以给出 *args 吗?
- sql - SSRS 报告中的 TM 符号字体问题