Add Environmentobject in Swiftui 2.0

Add EnvironmentObject in SwiftUI 2.0

Try the following:

@main
struct TestApp: App {
@StateObject var settings: Settings = ... // init here

var body: some Scene {
WindowGroup {
ContentView()
.environmentObject(settings)
}
}
}

SwiftUI: Using environment objects with Xcode 12/iOS 14 (-- How/where to place an object in the environment?)

You can create and inject it in scene of window group, like

@main
struct MyApp: App {
@StateObject var userSettings = UserSettings()

var body: some Scene {
WindowGroup {
ContentView().environmentObject(userSettings)
}
}
}

How to use EnvironmentObject in app file in SwiftUI

You can use it as regular property at that level and pass as environment down into view hierarchy if/when needed, like

struct ExampleApp: App {

let userAuth = UserAuth() // << here !!

var body: some Scene {
WindowGroup {
switch userAuth.loginStatus {
case .signedIn:
ContentView()
.environmentObject(userAuth) // << here !!
case .signedOut:
Text("Signed Out")
}
}
}
}

How to manage @ObservedObject and @EnvironmentObject on same Struct?

SwiftUI 2.0

Make it @StateObject, like

struct MenuView: View {

@EnvironmentObject var order: Order
@StateObject var model = DetailsModel()
...

SwiftUI 1.0

Inject it externally via constructor (having for it own life-cycle)

struct MenuView: View {

@EnvironmentObject var order: Order
@ObservedObject var model: DetailsModel
...

A View.environmentObject(_:) for AppInformation may be missing as an ancestor of this view

So first of all, your example code is not working.

  • Use @Published for your properties, then use Slider(value: $appInfo.duration, ...). This is because Slider is expecting a Binding (see https://developer.apple.com/documentation/swiftui/slider)
  • Use the struct Settings_Previews outside of struct Settings

Below you will find the fixed version. Both running in previews and in Simulator.

To answer your question:

If you use Settings anywhere in your Code, you have to pass it an environmentObject of AppInformation (See ContentView). Since you did not provide any source code in context I assume thats where your error is.

Here is a working example:

import SwiftUI
import CoreData

class AppInformation: ObservableObject {
@Published var duration = 0.0
@Published var interval = 0.0
}

struct Settings: View {
@EnvironmentObject var appInfo: AppInformation

var body: some View {
NavigationView {
ZStack {
VStack (spacing: 35){
HStack {
Text("Duration")
.font(.system(size: 23, weight: .bold, design: .rounded))
.padding(.leading, 25)
Spacer()

Slider(value: $appInfo.duration, in: 1...60, step: 1)
.padding([.trailing, .leading], 20)
Text("\(Int(appInfo.duration))")
.padding(.trailing, 30)
.font(.system(size: 23, weight: .medium, design: .rounded))
}
.padding(.top, 100)

HStack {
Text("Interval ")
.font(.system(size: 23, weight: .bold, design: .rounded))
.padding(.leading, 25)
Spacer()

Slider(value: $appInfo.interval, in: 1...60, step: 1)
.padding([.trailing, .leading], 20)
Text("\(Int(appInfo.interval))")
.padding(.trailing, 30)
.font(.system(size: 23, weight: .medium, design: .rounded))

}
Spacer()
}
}
.navigationTitle("Settings")
}
}
}

struct Settings_Previews: PreviewProvider {
static var previews: some View {
Settings()
.environmentObject(AppInformation())
}
}

struct ContentView: View {
@ObservedObject var appInformation = AppInformation()

var body: some View {
Settings()
.environmentObject(appInformation)
}

}

Also here are some tips using SwiftUI:

  • If you need to set padding on multiple edges you can use also use .padding([.trailing, .leading], 20)
  • You should set the .navigationTitle("Settings") modifier on the outer child of the view - but within the NavigationView
  • You can also set the .font modifier on the VStack or HStack, this would apply it to all children (including the Slider Label)


Related Topics



Leave a reply



Submit