< How to use @ObservedObject to manage state from external objects | How to use @EnvironmentObject to share data between views > |
Updated for Xcode 12.0
Although using @Published
is the easiest way to control state updates, you can also do it by hand if you need something specific. For example, you might want the view to refresh only if you’re happy with the values you’ve been given.
Using this approach takes three steps: importing the Combine framework, adding a publisher, then using the publisher. Publishers are Combine’s way of announcing changes to whatever is watching, which in the case of SwiftUI is zero or more views.
Here’s an example in code:
import Combine
import SwiftUI
class UserAuthentication: ObservableObject {
let objectWillChange = ObservableObjectPublisher()
var username = "" {
willSet {
objectWillChange.send()
}
}
}
Let’s break down the code, to make it easier to understand. First, we have this:
let objectWillChange = ObservableObjectPublisher()
That creates an objectWillChange
property as an instance of ObservableObjetPublisher
. This comes from the Combine framework, which is why you need to add import Combine
to make your code compile. The job of an observable object publisher is simple: whenever we want to tell the world that our object has changed, we ask the publisher to do it for us.
Second, we have a willSet
property observer attached to the username
property of UserAuthentication
so that we can run code whenever that value changes. In our example code, we call objectWillChange.send()
whenever username
changes, which is what tells the objectWillChange
publisher to put out the news that our data has changed so that any subscribed views can refresh.
As our UserAuthentication
class conforms to ObservableObject
, we can use it just like any other @ObservedObject
property. So, we might use it like this to display the user’s entry as they type, like this:
struct ContentView: View {
@ObservedObject var settings = UserAuthentication()
var body: some View {
VStack {
TextField("Username", text: $settings.username)
.textFieldStyle(RoundedBorderTextFieldStyle())
Text("Your username is: \(settings.username)")
}
}
}
Note: SwiftUI actually provides us with a default objectWillChange
property, but it doesn’t actually work in the current beta. So, it’s important to declare your own with the same name.
SPONSORED Would you describe yourself as knowledgeable, but struggling when you have to come up with your own code? Fernando Olivares has a new book containing iOS rules you can immediately apply to your coding habits to see dramatic improvements, while also teaching applied programming fundamentals seen in refactored code from published apps.
Sponsor Hacking with Swift and reach the world's largest Swift community!
Link copied to your pasteboard.