SwiftUI для приложения macOS: пользователь @EnvironmentObject при закрытии окна и открытии другого - PullRequest
0 голосов
/ 07 января 2020

Мое приложение запускается с экрана входа в систему, где вы должны ввести учетные данные. Если вход выполнен успешно, текущее окно закрывается и открывается другое. В новом окне мне требуются некоторые из пользовательской модели (используемой во время входа в систему) для выполнения других запросов к API (базовая c аутентификация).

Иерархия: ContentView -> LoginView () -> MainPageView ( )

AppDelegateCode:

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)
    }
}

}

Когда я хочу использовать @EnvironmentObject в дочернем представлении MainPageView, я сталкиваюсь со следующей ошибкой:

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, потому что я закрыл окно и открыл другое в блоке действий кнопки входа в систему.

Есть ли способ связать два представления в swiftUI?

1 Ответ

0 голосов
/ 07 января 2020

Нашел решение. В LoginView я объявил экземпляр CreateUserViewModel с оболочкой свойства @ObservedObject и передал его в MainPageView, что также требовало добавить новое свойство в MainPageView типа CreateUserViewModel.

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)
                    }

MainPageView:

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.

Я все еще не могу ios, если есть способ использовать @EnvironmentObject в этом сценарии.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...