【问题标题】:How to show data from a ObservableObject in Swiftui如何在 Swiftui 中显示来自 ObservableObject 的数据
【发布时间】:2022-02-27 07:19:08
【问题描述】:

我正在尝试使用 SwiftUI 制作一个小型社交媒体应用程序。 我创建了一个名为 user 的 ObservableObject 类和一个 Sign up 视图,其中 var 获得了价值。当我想在我的 ProfilView 中显示数据时,会发生错误。

线程 1:致命错误:未找到用户类型的 ObservableObject。 User 的 View.environmentObject(_:) 作为该视图的祖先可能会丢失。

主页是主视图,当按下按钮时,我会在视图之间切换,这是 AppInformation 中的布尔变化。

struct ProfileView: View {

@EnvironmentObject var appUser: User

@State var beschreibung: String = ""
@State var benutzername: String = ""
@State var name: String = ""

var body: some View {
    
    init() {
        benutzername = appUser.username
        name = appUser.name
    }
    
    ZStack {
Rectangle()
            .frame(width: 400, height: 720)
    .cornerRadius(50)
    .foregroundColor(.gray)
    .overlay(
        
    HStack {
    Image(systemName: "person.circle")
            .resizable()
            .frame(width: 100, height: 100)
            .onTapGesture {
                print("pressed")
            }
            .padding(20)
            .overlay(
                ZStack{
                    Rectangle()
                        .frame(width: 20, height: 20)
                        .offset(x: 35, y: -35)
                        .foregroundColor(.white)
                Image(systemName: "plus.circle.fill")
                    .resizable()
                    .frame(width: 30, height: 30)
                    .offset(x: 35, y: -35)
                    .foregroundColor(.blue)
                }
            )
            VStack {
                Text(benutzername)
                .font(.largeTitle)
                .frame(width: 240 ,alignment: .leading)
                .offset(x: -10, y: -25)
                .lineLimit(1)
                
                Text(name)
                .frame(width: 220, alignment: .leading)
                .offset(x: -15,y: -20)
                .lineLimit(1)
            }
        
        }
        .frame(width: 400, height: 720, alignment: .topLeading)
    )
    .padding()
        
        
        
        ZStack {
    Rectangle()
            .foregroundColor(.secondary)
            .frame(width: 380, height: 510)
            .cornerRadius(45)
        }
        .frame(width: 400, height: 700, alignment: .bottom)
        .padding()
        
    }
    .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top)
    }
}

class User: ObservableObject{

@Published var username: String = ""
@Published var name: String = ""
var password: String = ""
@Published var email: String = ""
@Published var beschreibung: String = ""

}

    @State var isSecured: Bool = true
@State var noPassword: Int = 0
@State var noEmail: Int = 0
@State var noUsername: Int = 0
@State var noName: Int = 0

@State var password: String = ""
@State var username: String = ""
@State var name: String = ""
@State var email: String = ""

@EnvironmentObject var appInfo: AppInformation
@EnvironmentObject var appUser: User

var body: some View {
    
    ZStack {
        
        RoundedRectangle(cornerRadius: 25)
            .frame(width: 380, height: 650)
            .overlay(Text("Erstelle Accout ")
                        .foregroundColor(.white)
                        .frame(width: 360, height: 510, alignment: .top)
                        .font(.headline))
        
        ZStack {
            
        VStack {
            
            TextField("Username", text: $username)
                .frame(width:180 ,height:40 ,alignment: .center)
                .multilineTextAlignment(.center)
                .font(.headline)
                .background(Color.gray.opacity(0.25))
                .clipShape(Capsule())
                .foregroundColor(.white)
                .border(.red, width: CGFloat(noUsername))
            
            Spacer()
                .frame(height: 35)
            
            TextField("Full name", text: $name)
                .frame(width:180 ,height:40 ,alignment: .center)
                .multilineTextAlignment(.center)
                .font(.headline)
                .background(Color.gray.opacity(0.25))
                .clipShape(Capsule())
                .foregroundColor(.white)
                .border(.red, width: CGFloat(noName))
            
            Spacer()
                .frame(height: 35)
            
            TextField("Email", text: $email)
                .frame(width:180 ,height:40 ,alignment: .center)
                .multilineTextAlignment(.center)
                .font(.headline)
                .background(Color.gray.opacity(0.25))
                .clipShape(Capsule())
                .foregroundColor(.white)
                .border(.red, width: CGFloat(noEmail))
            
            Spacer()
                .frame(height: 35)
        
            HStack {
                Spacer()
                    .frame(width: 37)
            if isSecured {
            SecureField("Password", text: $password)
                    .frame(width:180 ,height:40 ,alignment: .center)
                    .multilineTextAlignment(.center)
                    .font(.headline)
                    .background(Color.gray.opacity(0.25))
                    .clipShape(Capsule())
                    .foregroundColor(.white)
                    .border(.red, width: CGFloat(noPassword))
            } else {
                TextField("Password", text: $password)
                    .frame(width:180 ,height:40 ,alignment: .center)
                    .multilineTextAlignment(.center)
                    .font(.headline)
                    .background(Color.gray.opacity(0.25))
                    .clipShape(Capsule())
                    .foregroundColor(.white)
                    .border(.red, width: CGFloat(noPassword))
            }
        
                ZStack {
                Button("     ") {
                    isSecured.toggle()
                    print(isSecured)
                }
                Image(systemName: self.isSecured ? "eye" : "eye.slash")
                    .foregroundColor(.gray)
                }
            }
            
            Spacer()
                .frame(height: 60)
            
            Button("Erstellen"){
                
                if username == "" {
                    noUsername = 1
                    
                    if name == "" {
                        noName = 1
                        
                        if email == "" {
                            noEmail = 1
                            
                            if password == "" {
                                noPassword = 1
                            }
                        }
                        else if password == "" {
                            noPassword = 1
                        }
                    }
                    else if email == "" {
                        noEmail = 1
                    
                        if password == "" {
                            noPassword = 1
                        }
                    }
                    else if password == "" {
                        noPassword = 1
                    }
                }
                else if name == "" {
                    noName = 1
                    
                    if email == "" {
                      noEmail = 1
                        
                        if password == "" {
                            noPassword = 1
                        }
                    }
                    else if password == "" {
                          noPassword = 1
                    }
                }
                else if email == "" {
                    noEmail = 1
                    
                    if password == "" {
                          noPassword = 1
                    }
                }
                else if password == "" {
                    noPassword = 1
                }
                
                else {
                    appUser.username = username
                    appUser.email = email
                    appUser.password = password
                    appUser.name = name
                    
                    appInfo.finished = true
                }
        }
        .font(.headline)
        .frame(width: 150, height: 50)
        .background(.blue)
        .foregroundColor(.white)
        .clipShape(Capsule())
        }
    }
}

} }

class AppInformation: ObservableObject{

@Published var home: Bool = true
@Published var camera: Bool = false
@Published var friends: Bool = false
@Published var profil: Bool = false

@Published var showBar: Bool = true

@Published var finished: Bool = false

}

struct Home: View {

@EnvironmentObject var appInfo: AppInformation
@EnvironmentObject var appUser: User
    
var body: some View {
    ZStack {
        
    if appInfo.finished {
        
        if appInfo.home {
            HomeView()
        }
        else if appInfo.camera {
            MakePostView()
        }
        else if appInfo.friends {
            FriendsView()
        }
        else if appInfo.profil {
            ProfileView()
            .environmentObject(appUser)
        }
            if appInfo.showBar {
                NavigationBar()
            }
        }
        
        else {
            ErstellenView().environmentObject(appInfo)
                           .environmentObject(appUser)
        }
    }
}

}

【问题讨论】:

  • 错误告诉你没有传递Home中的@EnvironmentObject var appUser: User所需的User对象。因此,在Home 视图之前的层次结构中的某处,您应该创建了一个@StateObject var appUser = User(),并使用.environmentObject(appUser) 将其传递给Home。或者,在 Home 中将 @EnvironmentObject var appUser: User 替换为 @StateObject var appUser = User()。请注意,同样在 ProfileView 中,视图主体内不能有 init(),请将其放在外面。
  • 嗨,我已经做到了
  • workingdog 是对的,你在某处错过了它。
  • 错误是因为EnvironmentObjects,即使正确地注入到视图层次结构中,在初始化时也不一定可用。因此,要么将依赖项直接传递给你的 init,要么在其他地方进行设置(如 onAppear)

标签: swift xcode swiftui


【解决方案1】:

ProfileView 中,视图主体内不能有init()。 完全删除init(),直接使用appUser.usernameappUser.name,如: Text(appUser.username)Text(appUser.name) 。这就是使用 User ObservableObject 模型的目的。无需创建 局部变量。当您尝试在init() 中访问appUser 时,EnvironmentObject 不会准备好,它将是...missing as an ancestor of this view。换句话说,您不应该在init() 中使用EnvironmentObject

【讨论】:

    【解决方案2】:

    User 应该是一个结构并使其成为 appInfo 对象上的已发布属性。我们通常只有一个环境对象保存模型结构,我们通常将其称为模型而不是 appInfo。

    appInfo 中的大多数现有布尔值应该在 View 结构中的 @State var bool 中,相关的可以一起在 @State var 结构中,并且您可以使用变异函数来操作数据。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-06-24
      • 2023-03-15
      • 1970-01-01
      • 2021-04-04
      • 2019-11-01
      • 2021-12-14
      • 2020-06-25
      相关资源
      最近更新 更多