iam trying to make an small Social Media App with SwiftUI. I creat a ObservableObject class called user and an Sign up view where the var get there value. When iam tying to show the Data in my ProfilView a Error happens.
Thread 1: Fatal error: No ObservableObject of type User found. A View.environmentObject(_:) for User may be missing as an ancestor of this view.
Home is the Main View where i switch between the views with a bar when an Button is pressed a bool change in 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)
}
}
}
}
CodePudding user response:
User should be a struct and make it a published property on the appInfo object. We usually only have one environment object holding the model structs and we usually call it model rather than appInfo.
Most of your existing bools in appInfo should be in an @State var bool in the View struct and related ones could be together in an @State var struct and you can use mutating funcs to manipulate the data.
CodePudding user response:
In ProfileView
you must not have init()
inside the view body.
Remove init()
completely, and instead, use appUser.username
and appUser.name
directly, such as:
Text(appUser.username)
and Text(appUser.name)
. This is the purpose of using a User
ObservableObject
model. There is no need to create a
local variable. When you try to access appUser
in init()
the EnvironmentObject
will not be ready.