Is passing a class into the .environmentObject modifier equivalent to creating a kind of Singleton?

101 Views Asked by At

Apple loves singletons but Singletons are considered bad practice and I am trying to remove them from an app I am converting to SwiftUI.

I have a singleton for App Store Purchases and Restores which is initialized when the app starts and contains a closure that will be called to update the database if a result comes from the App Store. The updates have nothing to do with the interface.

Something like this

let myAppStoreSingleton = MyAppStoreSingleton.sharedInstante
myAppStoreSingleton.initialize(runOnPurchase: { success() }, runOnFailure: { failure() })

As you know, the results will come async.

Now suppose that the result takes too long to arrive and the user thinks an error happened and moved to another screen. Does not matter because the singleton is there, on memory, and will run one of the closures when the result comes.

Now suppose I create a regular class and pass it on MyApp.swift as a .environmentObject(MyAppStorePurchaseClass), like this:

let myAppStoreClass = MyAppStoreClass()
myAppStoreClass.initialize(runOnPurchase: { success() }, runOnFailure: { failure() })

Adding this to MyApp.swift...

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

Two questions:

  1. It will produce the same effect as the singleton, right? It is sitting on memory and will run the closures runOnPurchase or runOnFailure when the results come, right?
  2. will myAppStoreClass be available on either classes and views, by retrieving it with the @Environment wrapper?
1

There are 1 best solutions below

4
On BEST ANSWER

No, .environmentObject() is simply convenience to save you from having to pass an ObservableObject into every view until reaching the one it is needed in. So you can set .environmentObject at the top level and then access it down at the View you need it in. It's also possible to override an object on the way down but that is an advanced feature.

For your purposes it sounds like you might not need an object at all. Check out EnvironmentKey maybe you could use that? And there is an interesting built-in controller struct AuthorizationController that is defined as a key.