NEW: Get your ticket for Hacking with Swift Live 2019! >>

< What’s the difference between @ObjectBinding, @State, and @EnvironmentObject?   How to use @EnvironmentObject to share data between views >

How to use @ObjectBinding to create object bindings

When using object bindings there are two ever so slightly differently things we need to work with: the BindableObject protocol is used with some sort of class that can store data, and the @ObjectBinding property wrapper is used inside a view to store a bindable object instance.

As an example, here’s a UserSettings class that conforms to BindableObject:

class UserSettings: BindableObject {
    var didChange = PassthroughSubject<Void, Never>()

    var score = 0 {
        didSet {
            didChange.send(())
        }
    }
}

That packs quite a lot into a small amount of space, so let me break it down.

First: didChange is an instance of PassthroughSubject. This comes from the Combine framework, you’ll need to add import Combine to make your code compile. The job of a passthrough subject is simple: whenever we want to tell the world that our object has changed, we ask the passthrough subject to do it for us. It’s called “pass through” because the value we hand it literally gets passed on to whatever views are watching for changes. PassthroughSubject is technically called a publisher, because it publishes announcements of changes to the world.

Second: PassthroughSubject is generic over two things: Void and Never. The first parameter, Void, means “I will send no value.” In the case of SwiftUI we don’t need a value to send because all we want is for the view to refresh – it will automatically pick up the new data from its @ObjectBinding state. The second parameter, Never, means “I will never throw errors.” If you wanted to, you could define a custom error type such as NetworkError and send that instead, but again it’s usually find to handle errors locally inside your bindable object.

Third: we have a didSet property observer attached to the score property of UserSettings so that we can run code whenever that value changes. In our example code, we call didChange.send(()) whenever score changes, which is what tells the didChange publisher to put out the news that our data has changed so that any subscribed views can refresh.

We can use that UserSettings class inside a view like this:

struct ContentView : View {
    @ObjectBinding var settings = UserSettings()

    var body: some View {
        VStack {
            Text("Your score is \(settings.score)")
            Button(action: {
                self.settings.score += 1
            }) {
                Text("Increase Score")
            }
        }
    }
}

As you can see, other than using the @ObjectBinding property wrapper with settings, everything else more or less looks the same – SwiftUI takes care of all the implementation details for us.

There is one important difference, though: the settings property isn’t declared as private. This is because bound objects can be used by more than one view, so it’s common to share it openly.

Warning: When you use a publisher to announce that your object has changed, this must happen on the main thread.

HACKING WITH SWIFT LIVE This July is a new two-day event where you'll be inspired by great speakers on day one then learn all the amazing new features from WWDC on day two – click here for more information and tickets.

< What’s the difference between @ObjectBinding, @State, and @EnvironmentObject?   How to use @EnvironmentObject to share data between views >
MASTER SWIFT NOW
Buy Testing Swift Buy Practical iOS 12 Buy Pro Swift Buy Swift Design Patterns Buy Swift Coding Challenges Buy Server-Side Swift (Vapor Edition) Buy Server-Side Swift (Kitura Edition) Buy Hacking with macOS Buy Advanced iOS Volume One Buy Advanced iOS Volume Two Buy Hacking with watchOS Buy Hacking with tvOS Buy Hacking with Swift Buy Dive Into SpriteKit Buy Swift in Sixty Seconds Buy Objective-C for Swift Developers Buy Beyond Code

Was this page useful? Let me know!

Average rating: 5.0/5

Click here to visit the Hacking with Swift store >>