Derived Behavior: The Problem

Episode #146 • May 17, 2021 • Subscriber-Only

The ability to break down applications into small domains that are understandable in isolation is a universal problem, and yet there is no default story for doing so in SwiftUI. We explore the problem space and a possible solution in vanilla SwiftUI before turning our attention to the Composable Architecture.

The Problem
Introduction
00:05
A moderately complex SwiftUI application
02:28
Child-parent view model communication
14:08
Parent-child view model communication
25:56
Next time: the Composable Architecture
39:18

Unlock This Episode

Our Free plan includes 1 subscriber-only episode of your choice, plus weekly updates from our newsletter.

Introduction

There’s a large complex problem that we all grapple with when making applications, but it’s not often addressed head on and given a systematic study. Our applications are built as large blobs of state, which represents the actual data of the application, and behavior to evolve that state over time. Now this big blob of data and behavior is extremely difficult to understand all at once. It’s of course all there, even if some parts are hidden away in little implicit chunks of state and behavior, but ideally we could cook up tools and techniques that allow us to understand only a small part of the application at once.

Doing this comes with huge benefits. Things like improved compile times, allowing yourself to build and run subsets of your application in isolation, strengthening the boundaries between components to make them more versatile, and more. We’ve definitely harped on these concepts over and over on Point-Free, but there’s still more to say.

We want to explore the heart of this problem from first principles. We’ll start with a vanilla SwiftUI application that has two separate screens, each with their own behavior and functionality, but they also need to share a little bit of functionality. Further, the parent screen that encapsulates the two children also wants to be able to observe the changes in each of the children.

This is a surprisingly subtle interaction to get right, especially in vanilla SwiftUI. The crux of the problem is that we want to be able to bundle up most or all of our application’s behavior into a single object, and then derive new objects from it that contain only a subset of the behavior. So, we could take the root application domain and derive smaller and smaller domains. For example, we take the app-level object and derive an object for just the home screen, and then further derive from that an object for the profile screen, and then further derive from that an object for the settings screen, all the while these derived objects will stay in sync with each other so that the changes in one are instantly reflected in the others.

Now, if you are a user of our Composable Architecture library this all probably sounds very similar to the concept of Stores and .scopes, and you’re right, but we want to use vanilla SwiftUI as a jumping off point to dig even deeper into those concepts.

This episode is for subscribers only.

Subscribe to Point-Free

Access this episode, plus all past and future episodes when you become a subscriber.

See plans and pricing

Already a subscriber? Log in

References

@StateObject and @ObservedObject in SwiftUI

Matt Moriarity • Friday Jul 3, 2020

In this episode we only considered @ObservedObject, but there’s also something called @StateObject that can be handy for giving some behavior responsibilities to a child domain. This article describes in detail how each of the objects work under the hood and when it’s appropriate to use each one.

Data Essentials in SwiftUI

Apple • Monday Jun 22, 2020

In this WWDC session from 2020 Apple engineers describe how to best wield @ObservedObjects and @StateObjects. Starting at around 12:30 in the video they hint at the possibility of breaking up large observable objects into smaller “projections”, but stop short of showing code on how to accomplish this and never released the source code of the demo project unfortunately. Hopefully WWDC 2021 will bring some solutions 🤞.

Nested Observable Objects in SwiftUI

Joseph Heck • Saturday Feb 13, 2021

This is one of the few articles in the community that addresses how to derive child behavior from a parent. This article focuses on how to notify the parent when child state changes, but extra work must be done if one wants to share state between child and parent.

Child stores

Daniel Peter • Sunday Jun 28, 2020

In the absence of Apple providing source code for the demo application used in Data Essentials many have wondered what Apple had in mind for the solution. This Twitter thread details some people’s conjectures, including Daniel Peter’s conjecture which is almost exactly the solution we came up with in this episode.

Downloads