By using this site, you agree to the Privacy Policy and Terms of Use.
Accept
World of SoftwareWorld of SoftwareWorld of Software
  • News
  • Software
  • Mobile
  • Computing
  • Gaming
  • Videos
  • More
    • Gadget
    • Web Stories
    • Trending
    • Press Release
Search
  • Privacy
  • Terms
  • Advertise
  • Contact
Copyright © All Rights Reserved. World of Software.
Reading: The Difference Between EnvironmentObject, StateObject, ObservedObject & Observable | HackerNoon
Share
Sign In
Notification Show More
Font ResizerAa
World of SoftwareWorld of Software
Font ResizerAa
  • Software
  • Mobile
  • Computing
  • Gadget
  • Gaming
  • Videos
Search
  • News
  • Software
  • Mobile
  • Computing
  • Gaming
  • Videos
  • More
    • Gadget
    • Web Stories
    • Trending
    • Press Release
Have an existing account? Sign In
Follow US
  • Privacy
  • Terms
  • Advertise
  • Contact
Copyright © All Rights Reserved. World of Software.
World of Software > Computing > The Difference Between EnvironmentObject, StateObject, ObservedObject & Observable | HackerNoon
Computing

The Difference Between EnvironmentObject, StateObject, ObservedObject & Observable | HackerNoon

News Room
Last updated: 2026/03/02 at 6:57 PM
News Room Published 2 March 2026
Share
The Difference Between EnvironmentObject, StateObject, ObservedObject & Observable | HackerNoon
SHARE

@StateObject, @EnvironmentObject, and @ObservedObject

I’ve decided to dedicate this week to exploring data flow in SwiftUI. In this article, we’ll discuss the differences between the @StateObject, @EnvironmentObject, and @ObservedObject property wrappers. From my experience, this is often the most confusing topic for developers just starting out with SwiftUI.

Why do we need property wrappers in SwiftUI?

SwiftUI uses immutable struct types to describe the view hierarchy. Every view provided by the framework is inherently immutable. This is why SwiftUI provides a specific set of property wrappers to handle data changes.

Property wrappers allow us to declare variables inside our SwiftUI views while the actual data is stored externally, outside the view that declares the wrapper. This mechanism ensures that when the data changes, the view can stay in sync and rerender appropriately.

@StateObject

@StateObject is a property wrapper that instantiates a class conforming to the ObservableObject protocol and stores it in SwiftUI’s internal memory.

The key characteristic of @StateObject is that SwiftUI creates only one instance for each container that declares it, keeping that instance alive independently of the view’s lifecycle (even if the view is identity-recreated).

Let’s look at a few examples where we use @StateObject to preserve the state across the entire application.

import SwiftUI

@main
struct CardioBotApp: App { 
    @StateObject var store = Store( 
    initialState: AppState(),
    reducer: appReducer, 
    environment: AppEnvironment(service: HealthService()) 
  )  
    var body: some Scene { 
      WindowGroup { 
        RootView().environmentObject(store) 
      } 
    }
}

As demonstrated, @StateObject is ideally suited for maintaining application-wide state and distributing it across various scenes or views. SwiftUI persists this data within the framework’s specialized memory, ensuring it remains secure and independent of any specific scene or view lifecycle.

@ObservedObject @ObservedObject provides another mechanism for subscribing to and monitoring changes in an ObservableObject. However, unlike @StateObject, SwiftUI does not manage the lifecycle of an @ObservedObject—that responsibility falls entirely on the developer. This property wrapper is perfect for scenarios where an ObservableObject is already owned by a @StateObject elsewhere and needs to be passed down to a reusable view.

I specifically emphasize reusable views because I utilize a CalendarContainerView in multiple contexts within my app. To keep the view modular and decoupled from the external environment, I use @ObservedObject to explicitly inject the data required for each particular instance.

NavigationLink( 
      destination: CalendarContainerView( 
      store: transformedStore, 
      interval: .twelveMonthsAgo 
      )
    ) { 
      Text("Calendar")
    }

@EnvironmentObject

@EnvironmentObject is a powerful mechanism for implicitly injecting an ObservableObject into a specific branch of your view hierarchy. Imagine your application features a module consisting of three or four screens—all of which rely on the same ViewModel. To avoid the repetitive boilerplate of explicitly passing that ViewModel through every single view layer (a challenge often referred to as “prop drilling”), @EnvironmentObject is the ideal solution. Let’s dive into how we can implement it effectively.

@main
struct CardioBotApp: App { 
  @StateObject var store = Store( 
      initialState: AppState(), 
      reducer: appReducer, 
      environment: .production )  

  var body: some Scene { 
      WindowGroup { 
          TabView { 
              NavigationView { 
                SummaryContainerView() 
                  .navigationBarTitle("today") 
              .environmentObject( 
            store.derived( 
                deriveState: .summary, 
                embedAction: AppAction.summary 
              ) 
            ) 
          }  
          NavigationView { 
            TrendsContainerView()
                .navigationBarTitle("trends") 
                .environmentObject( 
            store.derived( 
                deriveState: .trends,
                embedAction: AppAction.trends ) 
              ) 
          } 
        } 
      } 
    }
}

In the example above, we inject the environment object into the SummaryContainerView hierarchy. SwiftUI implicitly grants all child views residing within SummaryContainerView access to these injected objects. We can then seamlessly retrieve and subscribe to the data by employing the @EnvironmentObject property wrapper.

struct SummaryContainerView: View {
       @EnvironmentObject var store: Store<SummaryState, SummaryAction>  
        var body: some View { //......

It is essential to highlight that @EnvironmentObject shares the same lifecycle behavior as @ObservedObject. This implies that if you instantiate the object within a view that SwiftUI may recreate, a new instance of that environment object will be generated every time the view is re-initialized.

The iOS 17 Game Changer: The @Observable Macro

While understanding @StateObject, @ObservedObject, and @EnvironmentObject is crucial for maintaining older codebases, iOS 17 and Swift 5.9 introduced a paradigm shift: the @Observable macro. If your app targets iOS 17 and above, this is the modern, preferred approach to data flow.

What is it? Instead of conforming to the ObservableObject protocol and manually marking properties with the @Published wrapper, you simply annotate your class with the @Observable macro.

The “Killer Feature”: Granular Dependency Tracking 

The absolute biggest advantage of @Observable over the older property wrappers is performance through granular UI updates.

With the legacy ObservableObject, if a view observes an object, any change to any @Published property will trigger a re-render of that view—even if the view doesn’t actually use the changed property.

The @Observable macro changes this completely. SwiftUI now tracks exactly which properties are read inside a view’s body. If a property changes, only the views that explicitly read that specific property are invalidated and redrawn. This drastically reduces unnecessary view updates, leading to a much smoother and more performant application, especially in complex architectural setups.

Boilerplate Reduction: A Comparison

Let’s look at how much cleaner our architecture becomes.

The Old Way (Pre-iOS 17):

class UserSettings: ObservableObject { 
      @Published var username: String = "Guest" 
      @Published var isLoggedIn: Bool = false
}

struct ProfileView: View { 
      @StateObject private var settings = UserSettings()

      var body: some View { 
            Text("Hello, (settings.username)") 
        }
}

The New Way (iOS 17+ with @Observable):

@Observable 
class UserSettings { 
    var username: String = "Guest" 
    var isLoggedIn: Bool = false
}

struct ProfileView: View { 

      @State private var settings = UserSettings() 

       var body: some View { 
          Text("Hello, (settings.username)") 
          }
}

Why it’s a better solution:

  1. No more @Published: Every property in an @Observable class is observable by default, unless you explicitly mark it with @ObservationIgnored.

  2. Simplified Property Wrappers: * @StateObject is replaced by the standard @State.

  • @ObservedObject is no longer needed at all. You just pass the object as a standard let or var to your reusable views.
  • @EnvironmentObject is replaced by the simpler @Environment.

3. Framework Independence: @Observable is part of the Swift standard library, not the Combine framework. This makes your view models cleaner and less tightly coupled to UI-specific frameworks.

Conclusion: Choosing the Right Tool for the Job

Mastering data flow in SwiftUI is the foundation of building a robust, scalable, and clean architecture. Choosing the wrong property wrapper can lead to unexpected bugs, memory leaks, or massive performance bottlenecks.

Here is a quick cheat sheet to remember when to use which:

@StateObject: Use this as the source of truth. It is responsible for creating and owning the ObservableObject. Use it when a view needs to instantiate a ViewModel and keep it alive across view redraws.

@ObservedObject: Use this for passing data. It is used when a view needs to react to an ObservableObject that was created somewhere else (usually passed down from a parent view).

@EnvironmentObject: Use this for global or deep-hierarchy data. It is perfect for injecting dependencies (like themes, user sessions, or shared ViewModels) deep into a module without the boilerplate of prop drilling.

@Observable (iOS 17+): The modern standard. If your deployment target allows it, default to the @Observable macro. It eliminates boilerplate, replaces @StateObject and @ObservedObject with standard state properties, and provides vastly superior performance through granular dependency tracking.

Understanding the subtle differences between these tools is not just crucial for writing bulletproof SwiftUI code — it’s also one of the most common topics you will encounter in any advanced iOS developer interview.

Thanks for reading! If you found this breakdown helpful, stay with me and follow here also:

Linkedin n Github

Sign Up For Daily Newsletter

Be keep up! Get the latest breaking news delivered straight to your inbox.
By signing up, you agree to our Terms of Use and acknowledge the data practices in our Privacy Policy. You may unsubscribe at any time.
Share This Article
Facebook Twitter Email Print
Share
What do you think?
Love0
Sad0
Happy0
Sleepy0
Angry0
Dead0
Wink0
Previous Article The Best 4K Laptops We’ve Tested for 2026 The Best 4K Laptops We’ve Tested for 2026
Next Article Missiles made in Ukraine are bringing Putin’s invasion home to Russia Missiles made in Ukraine are bringing Putin’s invasion home to Russia
Leave a comment

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Stay Connected

248.1k Like
69.1k Follow
134k Pin
54.3k Follow

Latest News

3 Bluetooth Gadgets That Work With Your Amazon Fire TV Stick – BGR
3 Bluetooth Gadgets That Work With Your Amazon Fire TV Stick – BGR
News
Infrastructure is back as Orange Business drives trusted agentic platforms | Computer Weekly
Infrastructure is back as Orange Business drives trusted agentic platforms | Computer Weekly
News
La Liga Soccer: Stream Real Madrid vs. Atlético Madrid Live From Anywhere
La Liga Soccer: Stream Real Madrid vs. Atlético Madrid Live From Anywhere
News
7 Of The Best Android Phones With A Headphone Jack In 2026 – BGR
7 Of The Best Android Phones With A Headphone Jack In 2026 – BGR
News

You Might also Like

AWS at 20*: Inside the rise of Amazon’s cloud empire, and what’s at stake in the AI era
Computing

AWS at 20*: Inside the rise of Amazon’s cloud empire, and what’s at stake in the AI era

48 Min Read
Overview of Artificial Intelligence in 2026 – Chat GPT AI Hub
Computing

Overview of Artificial Intelligence in 2026 – Chat GPT AI Hub

13 Min Read
Overview of Artificial Intelligence in 2026 – Chat GPT AI Hub
Computing

Advancements in Neural Network Architectures – Chat GPT AI Hub

15 Min Read
The Impact of GPT-5.2 and Sora on AI in 2026: What You Need to Know – Chat GPT AI Hub
Computing

The Impact of GPT-5.2 and Sora on AI in 2026: What You Need to Know – Chat GPT AI Hub

18 Min Read
//

World of Software is your one-stop website for the latest tech news and updates, follow us now to get the news that matters to you.

Quick Link

  • Privacy Policy
  • Terms of use
  • Advertise
  • Contact

Topics

  • Computing
  • Software
  • Press Release
  • Trending

Sign Up for Our Newsletter

Subscribe to our newsletter to get our newest articles instantly!

World of SoftwareWorld of Software
Follow US
Copyright © All Rights Reserved. World of Software.
Welcome Back!

Sign in to your account

Lost your password?