使用 EnvironmentObject(按钮和导航视图)切换视图不起作用

Posted

技术标签:

【中文标题】使用 EnvironmentObject(按钮和导航视图)切换视图不起作用【英文标题】:Switching Views using EnvironmentObject (Button and Navigation View) not working 【发布时间】:2020-09-28 19:27:09 【问题描述】:

我想做什么?

我构建了一个应用程序,您可以在其中查看不同的讲座。您应该从导航视图中选择一个讲座,然后单击开始讲座并继续阅读。

应用程序是如何构建的?

第 0 页: MainMenuView - 显示 5 个项目(讲座)的 NavigationView

//
//  MainMenuView.swift
//  NewCareerFriends
//
//  Created by Tobias Reidl on 20.09.20.
//  Copyright © 2020 Tobias Reidl. All rights reserved.
//

import SwiftUI

struct MainMenuView: View 

    @State private var model = Topic.all()
    @EnvironmentObject var viewRouter: ViewRouter

    
    var body: some View 
       

        ZStack
        
        //Background
        Rectangle()
            .edgesIgnoringSafeArea(.all)
            .foregroundColor(Color(.white))
            
        VStack
        
        //Logo at the Top
        Image("careerfriends_logo_transparent")
            .resizable()
            .scaledToFit()
            .padding()
            .background(Color("card2"))
            .cornerRadius(10)
            .padding()
            .clipped()
            .shadow(color: Color.black.opacity(0.3), radius: 10, x: 0, y: 0)
        //Lectures as a Navigation View
        NavigationView
        List 

            ForEach(model)  topic in
                
                TopicCell(topic: topic)
        
        
        .navigationBarTitle(Text("Lektionen"))
        
        .cornerRadius(20)
        .padding()
        .shadow(radius: 10)
            



    // Custom Navigation View Design
    init() 
        // 1.
        UINavigationBar.appearance().backgroundColor = .white
       
        // 2.
        UINavigationBar.appearance().largeTitleTextAttributes = [
            .foregroundColor: UIColor.black,
            .font : UIFont(name:"Arial", size: 28)!]
                
        // 3.
        UINavigationBar.appearance().titleTextAttributes = [
            .font : UIFont(name: "Arial", size: 20)!]
    


// Previewer
struct MainMenuView_Previews: PreviewProvider 
    static var previews: some View 
        MainMenuView()
    


// Custom Cells for the NavigationView
struct TopicCell: View 
    
    let topic : Topic

    var body: some View 
        // Below is the error message
        return NavigationLink(destination: LectureFullView(topic: topic).environmentObject(ViewRouter()))
            
            HStack
                Image(topic.Image)
                    .resizable()
                    .scaledToFit()
                    .frame(width: 150, height: 160)
                    .cornerRadius(10)
                VStack
                    Text(topic.Title)
                        .font(.headline)
                        .frame(maxWidth: .infinity, alignment: .leading)
                    
                    Text(topic.Text)
                        .lineLimit(7)
                        .font(.system(size: 14))
                        .frame(maxWidth: .infinity, alignment: .center)
                
            
        
    

第 1 页: LectureFullView - 显示快速项目(讲座)介绍,“开始讲座”按钮

//
//  LectureFullView.swift
//  NewCareerFriends
//
//  Created by Tobias Reidl on 23.09.20.
//  Copyright © 2020 Tobias Reidl. All rights reserved.
//

import SwiftUI




struct LectureFullView: View 
    
    
    let topic : Topic
    
    @EnvironmentObject var viewRouter: ViewRouter
    
    var body: some View 
        ZStack
        
        
            ScrollView
            VStack
            Image(topic.Image)
                .resizable()
                .scaledToFit()
                .edgesIgnoringSafeArea(.all)
            Text(topic.Title)
                .font(.system(size: 32))
                .frame(maxWidth: .infinity, alignment: .center)
                
            Text(topic.Text)
                .font(.system(size: 17))
                .frame(maxWidth: .infinity, alignment: .center)
                .padding(.leading)
                .padding(.trailing)
                .padding(.bottom)
                
                
               
                VStack
                Button(action:
                
                    self.viewRouter.currentPage = "page2"
                )
                
                    Text("Lektion starten")
                    .font(.body)
                
                
                .padding(.bottom)
            

        
    


struct LectureFullView_Previews: PreviewProvider 
    static var previews: some View 
        LectureFullView(topic: Topic.all()[0]).environmentObject(ViewRouter())
    

第 2 页: LevelOneView - 展示讲座的第一部分

//
//  LevelOneView.swift
//  NewCareerFriends
//
//  Created by Tobias Reidl on 27.09.20.
//  Copyright © 2020 Tobias Reidl. All rights reserved.
//

import SwiftUI

struct LevelOneView: View 

    let topic: Topic
    @EnvironmentObject var viewRouter: ViewRouter
    
    var body: some View 
        ZStack
         
            VStack
                HStack
                    
                Button(action: 
                     //
                 )
                 
                Text("Zurück")
                    .font(.headline)
                    .padding()
                    .background(Color(.white))
                    .cornerRadius(10)
                    .clipped()
                    .shadow(color: Color.black.opacity(0.3), radius: 10, x: 0, y: 0)
                 
                Text("Teil 1")
                    .font(.largeTitle)
                    .padding()
                    .background(Color(.white))
                    .cornerRadius(10)
                    .clipped()
                    .shadow(color: Color.black.opacity(0.3), radius: 10, x: 0, y: 0)
                   
                    Button(action: 
                        self.viewRouter.currentPage = "Page1"
                    )
                    
                    Text("Weiter")
                        .font(.headline)
                        .padding()
                        .background(Color(.white))
                        .cornerRadius(10)
                        .clipped()
                        .shadow(color: Color.black.opacity(0.3), radius: 10, x: 0, y: 0)
                    
                
                    
                
                Spacer()
                InformationView(topic: topic)
                
                Spacer()
                
                Image("BannerWindow1")
                .resizable()
                .cornerRadius(10)
                .scaledToFit()
                .padding()
                .shadow(radius: 10)
            
        
    


struct LevelOneView_Previews: PreviewProvider 
    static var previews: some View 
        LevelOneView(topic: Topic.all()[0]).environmentObject(ViewRouter())
    


struct InformationView: View 
    
    let topic : Topic
    
    var body: some View 
        ScrollView
            
                Text(topic.Information01)
                
                Spacer()

            
        .padding()
        .background(Color(.white))
        .cornerRadius(10)
        .padding(.leading)
        .padding(.trailing)
        .clipped()
        .shadow(color: Color.black.opacity(0.3), radius: 10, x: 0, y: 0)
        
    
    

附加: LectureMotherView - 控制显示哪个视图

//
//  LectureMotherView.swift
//  NewCareerFriends
//
//  Created by Tobias Reidl on 27.09.20.
//  Copyright © 2020 Tobias Reidl. All rights reserved.
//

import SwiftUI

struct LectureMotherView: View 
    
//    @State var page: String = "page0"
    @EnvironmentObject var viewRouter: ViewRouter
    
    var body: some View 
        VStack
           
            if viewRouter.currentPage == "page1"
            
                LectureFullView(topic: Topic.all()[0])
            
            else if viewRouter.currentPage == "page2"
            
                LevelOneView(topic: Topic.all()[0])
            
            else if viewRouter.currentPage == "page0"
            
                MainMenuView()
            
            
        
    


struct LectureMotherView_Previews: PreviewProvider 
    static var previews: some View 
        LectureMotherView().environmentObject(ViewRouter())
    

附加: ViewRouter - 跟踪页面 0 到 2 上的更改

//
//  LectureMotherView.swift
//  NewCareerFriends
//
//  Created by Tobias Reidl on 27.09.20.
//  Copyright © 2020 Tobias Reidl. All rights reserved.
//

import SwiftUI

struct LectureMotherView: View 
    
//    @State var page: String = "page0"
    @EnvironmentObject var viewRouter: ViewRouter
    
    var body: some View 
        VStack
           
            if viewRouter.currentPage == "page1"
            
                LectureFullView(topic: Topic.all()[0])
            
            else if viewRouter.currentPage == "page2"
            
                LevelOneView(topic: Topic.all()[0])
            
            else if viewRouter.currentPage == "page0"
            
                MainMenuView()
            
            
        
    


struct LectureMotherView_Previews: PreviewProvider 
    static var previews: some View 
        LectureMotherView().environmentObject(ViewRouter())
    

附加:主题 - 存储数据

//
//  TopicModel.swift
//  NewCareerFriends
//
//  Created by Tobias Reidl on 23.09.20.
//  Copyright © 2020 Tobias Reidl. All rights reserved.
//

import Foundation
import SwiftUI

struct  Topic: Identifiable

    let id = UUID()
    let Title: String
    let Image: String
    let Text: String
    let Information01: String
    let Question: String


extension Topic

    static func all() -> [Topic]
    
        return [
            
            Topic(Title: "Job finden", Image: "Window1", Text: "Nach drei Semestern studieren sucht Tim nach einer Möglichkeit erste, fachliche Berufserfahrung zu sammeln. Hierzu macht er sich auf die Suche nach einem Job den er neben dem Studium ausüben kann. In dieser Lektion lernst du die grundlegenden Information um einen studentischen Job zu finden.",
                Information01: "Die Online Jobbörse ist der bekannteste Ort zum Jobs finden, allerdings gibt es oftmals andere und teilweise sogar effektivere Methoden. Über Bekannte oder Mitstudenten herauszufinden in welchem Unternehmen sie vielleicht sogar aktuell als Student tätig sind gibt dir ggf. die Möglichkeit viel vom Standard Bewerbungsprozess zu überspringen und direkt durch Empfehlung bevorzugt zu werden. Dies ist dann besonders ein Vorteil wenn du bisher noch nicht so viele Erfahrungen hast. Wenn dein Lebenslauf nicht unbedingt Bände spricht macht eine Empfehlung von einem Mitstudenten schon einiges aus, solange er natürlich selbst gute Arbeit leistet. ", Question: "Hallo"),
            
            
            
            Topic(Title: "Bewerben", Image: "Window2", Text: "Nachdem du einen interessanten Job gefunden hast geht es ans bewerben. Doch wie genau bewirbt man sich richtig als Student? Was ist gern gesehen und was verrufen? Sich bewerben ist ein bisschen wie Dating. Du möchtest der anderen Person deinen Wert zeigen, bzw. auf deine Attraktivität als Mitarbeiter aufmerksam machen. Je mehr du mit der anderen Person gemeinsam hast und je eher ihr von euren Werten und Einstellungen zueinander passt, desto wahrscheinlicher findet ihr euch interessant. Das Bewerbungsschreiben und das Vorstellungsgespräch sind sich im Grunde sehr ähnlich. Die folgenden Tipps sind deshalb ebenfalls für ein Vorstellungsgespräch relevant. ", Information01: "Dies ist eine INFO",  Question: "HalloHalli"),
            
            
            
            Topic(Title: "Interviews", Image: "Window3", Text: "„Hallo Tim. Vielen Dank für deine Bewerbung. Wir möchten dich gerne näher kennenlernen und schlagen dir ein persönliches Interview vor. Passt dir nächsten Mittwoch?“ Endlich hat es Tim geschafft zu einem Vorstellungsgespräch eingeladen zu werden. Aber was soll er ohne viel Berufserfahrung erzählen? Eigentlich ist das Vorstellungsgespräch gar nicht so schwierig zu meistern wie viele denken. Auch ohne Berufserfahrung kannst du viele interessante und spannende Dinge erzählen, die dein Gegenüber begeistern und dafür Sorge tragen, dass du den Job bekommst. ", Information01: "Dies ist eine INFO",  Question: "HalloHalli"),
            
            
            
            
            Topic(Title: "Selbstreflexion", Image: "Window4", Text: "Marie ist einige Monate in einem Werkstudenten Job und fragt sich nun, ob sie direkt fest beim Unternehmen einsteigen sollte, oder ob es nochmal sinnvoll wäre ein neuen Praktikum bzw. eine neue Werkstudententätigkeit zu verfolgen. Auf der einen Seite reizt es sie nochmal etwas neues zu machen, auf der anderen Seite hat sie Angst die falsche Entscheidung zu treffen und sich den Weg zurück zu verbauen.", Information01: "Dies ist eine INFO",  Question: "HalloHalli"),
            
            
            
            
            Topic(Title: "Mit Kollegen & Chef interagieren ", Image: "Window5", Text: "Du bist also mittendrin in deinen ersten Arbeitswochen und versucht einen guten Eindruck bei deinen Kollegen zu hinterlassen, was nicht einfach ist. Wie überall ist natürlich auch der erste Eindruck auf der Arbeit zum großen Teil entscheidend dafür, was die Menschen für ein Bild von dir haben. Besonders dein Team und dein Chef werden dies in den ersten Arbeitstagen genau beobachten. Lass uns am Beispiel von „Tim“ herausfinden, welche Verhaltensmuster mit hoher Wahrscheinlichkeit kompetent oder inkompetent von seinen Kollegen gedeutet werden.", Information01: "Dies ist eine INFO", Question: "HalloHalli"),
            
            
            
            
            Topic(Title: "Übernahme / Neuer Job", Image: "Window6", Text: "Stell dir vor du bist nun seit ein paar Monaten bei einem Unternehmen. Das Team ist super und das Unternehmen gefällt dir auch. Du kannst dir gut vorstellen fest anzufangen und möchtest schon vorab alle Weichen so stellen, dass vielleicht sogar dein Chef und deine Kollegen auf dich proaktiv zukommen. Um die Chancen bei einem Unternehmen fest einzusteigen zu steigern musst du zeigen, dass du alle Aufgaben die ein Festangestellter erledigt, ebenfalls kannst. Deine Strategie sollte also sein dir alle nötigen Fähigkeiten anzueignen.  Hast du die Grundlagen erlernt geht es darum ein wertgeschätztes und unersetzbares Teambestandteil zu werden. Dies gilt für den sozialen Umgang mit deinem Team und auch Chef. ", Information01: "Dies ist eine INFO",  Question: "HalloHalli"),
        ]
        
        
    

有什么问题?

第 1 页:当我单击“开始讲座”按钮时,没有任何反应。

会发生什么?

它应该显示 Page2

为什么我会瘦呢?

我读到导航视图和环境对象相处得不是很好。但是我不知道具体的问题是什么。

我会收到任何错误消息吗?

没有,一切正常

希望你们能帮帮我,我将不胜感激。

【问题讨论】:

【参考方案1】:

您需要在整个应用程序中使用相同的 ViewRouter 实例。

TopicCell 视图中,您正在创建ViewRouter 实例:

return NavigationLink(destination: LectureFullView(topic: topic).environmentObject(ViewRouter())) 

所以当你修改LectureFullView中的new实例时,原来的实例不会受到影响。

要解决此问题,您需要传递环境中已存在的相同实例:

struct TopicCell: View 
    @EnvironmentObject var viewRouter: ViewRouter // get EnvironmentObject
    
    let topic : Topic

    var body: some View 
        // pass the existing `viewRouter` to the destination view
        NavigationLink(destination: LectureFullView(topic: topic).environmentObject(viewRouter)) 
        ...

【讨论】:

哇,它成功了!非常感谢你的回答,你救了我的命!!

以上是关于使用 EnvironmentObject(按钮和导航视图)切换视图不起作用的主要内容,如果未能解决你的问题,请参考以下文章

包和导包

SwiftUI - 在 ObservableObject 类/依赖注入中使用 EnvironmentObject

在 watchOS 中使用 environmentObject

Java面向对象--包和导包

我可以在 SwiftUI 中对所有共享数据使用 @EnvironmentObject 吗?

如何在 SwiftUI 中使用 EnvironmentObject 初始化 State 属性?