UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

Which SwiftUI property wrapper to choose in any situation

Decide which property wrapper is the right choice for your needs.

Paul Hudson       @twostraws

SwiftUI uses property wrappers to understand how we create and store data in our views, but if you need helping choosing which property wrapper is right for you I've made a tool to help. To find the right property wrapper for you, answer the questions below 🚀

1. Are you storing a struct, an enum, or a class?

I want to store a struct or an enum.

2. Will the value change over time?

Yes, it will change as my app runs.

3. Are you creating the value in your view, or will it be passed in from somewhere else?

I'll be creating the value locally in my view.

4. Is the property being used to track some sort of user input?

Yes, this is will track an active gesture.

You should use the @GestureState property wrapper, like this:

@GestureState private var dragAmount = CGSize.zero

Although you could also use @State for this purpose, @GestureState is significantly more efficient.

You can learn more about the @GestureState property wrapper here: What is the @GestureState property wrapper?

Yes, this will track which view has keyboard focus.

You should use the @FocusState property wrapper, like this:

@FocusState private var isUsernameFocused: Bool

You can learn more about the @FocusState property wrapper here: What is the @FocusState property wrapper?

No, this is just a regular value.

You should use the @State property wrapper, like this:

@State private var username = "Taylor"

Technically there's nothing stopping you from using @State to store a class instance, but you wouldn't get notified of any changes so it's best to avoid this.

You can learn more about the @State property wrapper here: What is the @State property wrapper?

I'll be passing in the value from somewhere else.

You should use the @Binding property wrapper.

@Binding var username: String

Using @Binding means you'll need to pass the value into the view from somewhere else, but any changes you make to the value will be reflected in the original value too.

You can learn more about the @Binding property wrapper here: What is the @Binding property wrapper?

No, it won't change.

You don't need a property wrapper here, and can use a regular property instead. For example:

let username: String

You can learn more about properties here: Properties in Swift.

I want to store a class.

2. Is it an object you're creating locally in your view, or will it be created somewhere else and passed in to your view?

I'm creating the object locally in my view.

You should use the @StateObject property wrapper, like this:

@StateObject private var user = User()

Using @StateObject rather than @ObservedObject is important, because it tells SwiftUI your view owns the object. This will stop SwiftUI from accidentally destroying the object if your view is recreated.

You can learn more about the @StateObject property wrapper here: What is the @StateObject property wrapper?

The object will be passed in from somewhere else.

3. Will the object be in the SwiftUI environment, or do you want to pass it in manually?

The object will be in the SwiftUI environment.

You should use the @EnvironmentObject property wrapper, like this:

@EnvironmentObject var user: User

Important: if you fail to provide the object in the environment your app will crash.

You can learn more about the @EnvironmentObject property wrapper here: What is the @EnvironmentObject property wrapper?

I want to pass it in manually as a parameter.

You should use the @ObservedObject property wrapper, like this:

@ObservedObject var user: User

Using @ObservedObject rather than @StateObject is important, because it tells SwiftUI your view wants to be notified of changes without owning the object.

You can learn more about the @ObservedObject property wrapper here: What is the @ObservedObject property wrapper?

There are other property wrappers not included in this tool because they are designed for specific purposes, including:

  • @AppStorage, for reading and writing data in UserDefaults.
  • @Environment, for working with environment data that comes from SwiftUI.
  • @FetchRequest, for reading Core Data objects.
  • @Published, for automatically announcing changes to properties in observable objects.
  • @ScaledMetric, for adjusting a size based on the user's device settings.
  • @SceneStorage, for reading and writing data that belongs to the current scene.

If you'd like more information on how property wrappers work in SwiftUI, I have some articles that will help:

You might also want to read SwiftUI Property Wrappers from Donny Wals.

BUY OUR BOOKS
Buy Pro Swift Buy Pro SwiftUI Buy Swift Design Patterns Buy Testing Swift Buy Hacking with iOS Buy Swift Coding Challenges Buy Swift on Sundays Volume One Buy Server-Side Swift Buy Advanced iOS Volume One Buy Advanced iOS Volume Two Buy Advanced iOS Volume Three Buy Hacking with watchOS Buy Hacking with tvOS Buy Hacking with macOS Buy Dive Into SpriteKit Buy Swift in Sixty Seconds Buy Objective-C for Swift Developers Buy Beyond Code

Was this page useful? Let us know!

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.