Swiftui macOS应用程序的快捷界面:关闭窗口和打开另一窗口时的User@EnvironmentObject
我的应用程序以登录屏幕开始,您必须输入凭据,如果登录成功,当前窗口将关闭,另一个窗口将打开。在新窗口中,我需要一些来自用户模型(登录时使用)的数据来执行对api的其他请求(基本身份验证) 层次结构:ContentView->LoginView()->MainPageView() AppDelegateCode:Swiftui macOS应用程序的快捷界面:关闭窗口和打开另一窗口时的User@EnvironmentObject,swiftui,Swiftui,我的应用程序以登录屏幕开始,您必须输入凭据,如果登录成功,当前窗口将关闭,另一个窗口将打开。在新窗口中,我需要一些来自用户模型(登录时使用)的数据来执行对api的其他请求(基本身份验证) 层次结构:ContentView->LoginView()->MainPageView() AppDelegateCode: let contentView = ContentView() let userVM = CreateUserViewModel() // Create the win
let contentView = ContentView()
let userVM = CreateUserViewModel()
// Create the window and set the content view.
window = NSWindow(
contentRect: NSRect(x: 0, y: 0, width: 480, height: 300),
styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView],
backing: .buffered, defer: false)
window.center()
window.setFrameAutosaveName("Main Window")
window.contentView = NSHostingView(rootView: contentView.environmentObject(userVM))
window.makeKeyAndOrderFront(nil)
ContentView代码:
struct ContentView: View {
var body: some View {
LoginView()
}
struct LoginView: View {
@EnvironmentObject var userVM: CreateUserViewModel
//@ObservedObject var userVM: CreateUserViewModel = CreateUserViewModel()
@State private var showSignUpSheet: Bool = false
var body: some View {
VStack {
Text("LubeMarker")
.font(.title)
HStack {
Text("Email")
TextField("", text: self.$userVM.email)
}
HStack {
Text("Pass")
.padding([.trailing], 4)
SecureField("", text: self.$userVM.password)
}
HStack {
Button("Login") {
self.userVM.loginUser()
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
if self.userVM.loginUserMessage == "Login Successful" {
NSApplication.shared.keyWindow?.close()
let window = NSWindow(contentRect: NSRect(x: 20, y: 20, width: 480, height: 300), styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView], backing: .buffered, defer: false)
window.center()
window.setFrameAutosaveName("Primary Window")
window.contentView = NSHostingView(rootView: MainPageView().environmentObject(self.userVM))
window.makeKeyAndOrderFront(nil)
}
}
}
Button("Sign Up") {
self.showSignUpSheet = true
}
}
Text(userVM.loginUserMessage)
}
.padding([.leading, .trailing], 60)
//.frame(width: 300, height: 200)
.sheet(isPresented: self.$showSignUpSheet) {
SignUpView(showSingUpSheet: self.$showSignUpSheet)
}
}
}
登录视图代码:
struct ContentView: View {
var body: some View {
LoginView()
}
struct LoginView: View {
@EnvironmentObject var userVM: CreateUserViewModel
//@ObservedObject var userVM: CreateUserViewModel = CreateUserViewModel()
@State private var showSignUpSheet: Bool = false
var body: some View {
VStack {
Text("LubeMarker")
.font(.title)
HStack {
Text("Email")
TextField("", text: self.$userVM.email)
}
HStack {
Text("Pass")
.padding([.trailing], 4)
SecureField("", text: self.$userVM.password)
}
HStack {
Button("Login") {
self.userVM.loginUser()
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
if self.userVM.loginUserMessage == "Login Successful" {
NSApplication.shared.keyWindow?.close()
let window = NSWindow(contentRect: NSRect(x: 20, y: 20, width: 480, height: 300), styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView], backing: .buffered, defer: false)
window.center()
window.setFrameAutosaveName("Primary Window")
window.contentView = NSHostingView(rootView: MainPageView().environmentObject(self.userVM))
window.makeKeyAndOrderFront(nil)
}
}
}
Button("Sign Up") {
self.showSignUpSheet = true
}
}
Text(userVM.loginUserMessage)
}
.padding([.leading, .trailing], 60)
//.frame(width: 300, height: 200)
.sheet(isPresented: self.$showSignUpSheet) {
SignUpView(showSingUpSheet: self.$showSignUpSheet)
}
}
}
当我想在MainPageView的子视图中使用@EnvironmentObject时,我遇到以下错误:
Thread 1: Fatal error: No ObservableObject of type CreateUserViewModel found.
A View.environmentObject(_:) for CreateUserViewModel may be missing as an ancestor of this view.
我假设错误是由于LoginView和MainPageView之间没有父子关系,因为我关闭了窗口,并在login button操作块中打开了另一个窗口
有没有办法在swiftUI中链接这两个视图?找到了解决方案。在LoginView中,我用@ObservedObject属性包装器声明了CreateUserViewModel的一个实例,并将其传递给MainPageView,这也需要在CreateUserViewModel类型的MainPageView中添加一个新属性 LoginView:
@ObservedObject var userVM: CreateUserViewModel = CreateUserViewModel()
@State private var showSignUpSheet: Bool = false
var body: some View {
HStack {
Button("Login") {
self.userVM.loginUser()
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
if self.userVM.loginUserMessage == "Login Successful" {
let mainPage = MainPageView(userVM: self.userVM)
NSApplication.shared.keyWindow?.close()
let window = NSWindow(contentRect: NSRect(x: 20, y: 20, width: 480, height: 300), styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView], backing: .buffered, defer: false)
window.center()
window.setFrameAutosaveName("Primary Window")
window.contentView = NSHostingView(rootView: mainPage)
window.makeKeyAndOrderFront(nil)
}
主页视图:
struct MainPageView: View {
@State var selectedProduct: ProductTypes?
@State var showAddProductSheet: Bool = false
var userVM: CreateUserViewModel
var body: some View {
VStack(spacing: 0) {
HStack {
Button("Add Product") {
self.showAddProductSheet = true
}
.padding()
Spacer()
Text("Hello World")
}
}
.frame(minWidth: 480, minHeight: 300)
.sheet(isPresented: self.$showAddProductSheet) {
AddProductView(showAddProductSheet: self.$showAddProductSheet).environmentObject(self.userVM)
}
}
}
并从MainPageView将userVM作为环境对象传递给其他视图。我觉得只有使用@ObservedObject才能将关闭的窗口与新窗口连接起来
如果在这个场景中有办法使用@EnvironmentObject,我仍然很好奇。找到了一个解决方案。在LoginView中,我用@ObservedObject属性包装器声明了CreateUserViewModel的一个实例,并将其传递给MainPageView,这也需要在CreateUserViewModel类型的MainPageView中添加一个新属性 LoginView:
@ObservedObject var userVM: CreateUserViewModel = CreateUserViewModel()
@State private var showSignUpSheet: Bool = false
var body: some View {
HStack {
Button("Login") {
self.userVM.loginUser()
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
if self.userVM.loginUserMessage == "Login Successful" {
let mainPage = MainPageView(userVM: self.userVM)
NSApplication.shared.keyWindow?.close()
let window = NSWindow(contentRect: NSRect(x: 20, y: 20, width: 480, height: 300), styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView], backing: .buffered, defer: false)
window.center()
window.setFrameAutosaveName("Primary Window")
window.contentView = NSHostingView(rootView: mainPage)
window.makeKeyAndOrderFront(nil)
}
主页视图:
struct MainPageView: View {
@State var selectedProduct: ProductTypes?
@State var showAddProductSheet: Bool = false
var userVM: CreateUserViewModel
var body: some View {
VStack(spacing: 0) {
HStack {
Button("Add Product") {
self.showAddProductSheet = true
}
.padding()
Spacer()
Text("Hello World")
}
}
.frame(minWidth: 480, minHeight: 300)
.sheet(isPresented: self.$showAddProductSheet) {
AddProductView(showAddProductSheet: self.$showAddProductSheet).environmentObject(self.userVM)
}
}
}
并从MainPageView将userVM作为环境对象传递给其他视图。我觉得只有使用@ObservedObject才能将关闭的窗口与新窗口连接起来
如果有办法在这个场景中使用@EnvironmentObject,我仍然很好奇