Skip to content

Wait Up A Second…

Compare
Choose a tag to compare
@mergesort mergesort released this 11 Feb 18:07
· 68 commits to main since this release
ad47507

The highlight of this release a new async initializer for a Boutique Store, thanks to the contribution of @rl-pavel. This initializer solves two problems.

  1. Previously when an app was starting up you would have to wait for a Store to finish loading before moving onto your next task, ostensibly acting as a blocking procedure. The Store was fast so it was not very noticeable from a performance perspective, but depending on the state-driven interface you were constructing and how big your Store was, it could be noticeable.
  2. The main problem this caused was not being able to tell whether the items in your Store still hadn't loaded, or if they had loaded with zero items. I call this the empty state problem, where you would see your empty state screen displayed for a split second, and then your items would load into place. This was a suboptimal experience, but is now a thing of the past.

You shouldn't notice any changes when using the Store's initializer, but you will now have this fancy method that shows you if the store has finished loading.

await store.itemsHaveLoaded()

What this allows you to do is to drive a SwiftUI/UIKit/AppKit view based on the Store's state. A simplified example looks like this.

struct ItemListView: View {
    @State private var itemsHaveLoaded = false

    var body: some View {
        VStack {
            AlwaysVisibleBanner()

            if self.itemsHaveLoaded {
                if self.items.isEmpty {
                    EmptyStateView()
                } else {
                    ItemView(items: self.items)
                }
            } else {
                LoadingStateView()
            }
        }
        .task({
            try await self.itemsController.items.itemsHaveLoaded()
            self.itemsHaveLoaded = true
        })
    }
}

This is a a really readable solution to a tricky problem, so once again, thank you Pavel. 👏🏻


Breaking Changes

  • StoredValue.binding is now computed property rather than a StoredValue.binding() function.
  • I've added back the Store.Operation.add functions which allowed for chained operations, they were accidentally marked as deprecated, oops.