What is the purpose of objectWillChangeSequence compared to the onChange modifier in SwiftUI?

Viewed 51

The sample comes from a WWDC22 video called The SwiftUI cookbook for navigation.

A NavigationModel is created to store the navigation path.

  • When the view appears, the NavigationModel is loaded with SceneStorage's data if any exists.
  • Whenever the NavigationModel changes, its data representation is saved in SceneStorage, by watching a custom objectWillChangeSequence computed property.

This last point intrigues me: why not just use the .onChange modifier? Like this:

.onChange(of: navModel.path) { _ in
    data = navModel.jsonData
}

NB: the objectWillChangeSequence property is defined like this:

var objectWillChangeSequence: AsyncPublisher<Publishers.Buffer<ObservableObjectPublisher>> {
    objectWillChange.buffer(size: 1, prefetch: .byRequest, whenFull: .dropOldest).values
}

enter image description here

1 Answers

Sadly I don't think the coder of the sample shown in the video a knew what they were doing. I also don't think it is necessarily Curt's fault probably some intern wrote the code for him.

The code sample is seriously flawed in that the Recipe struct has let id = UUID() which means even if the navigation path is restored, the recipe that was previously viewed would never be found because it has a different ID from when it was persisted.

We can fix it with this:

struct Recipe: Hashable, Identifiable {
    var id: String {
        return name
    }

Now the @SceneStorage will start working and we can test replacing it with onChange(.

We quickly find out that NavigationModel has more than recipePath, there is also selectedCategory and columnVisibility. If we were to use onChange with jsonData then we would be needlessly doing an encode just to check if there has been a change.

Related