Nil Coalescing Newsletter - October 2025

Hi there,

I hope you've had a productive October! Here in New Zealand, spring is finally in full bloom, so we've been spending more time in the garden and started some long-awaited house renovations.

I've also started updating my books for iOS 26, released an update for my app Breve with a special Halloween event, and recorded a Swift Academy podcast episode with Walid SASSI, which will be out in just a few days.

Let's dive into this month's updates!


SwiftUI Fundamentals updated for iOS 26

Earlier this month I published a new edition of my book SwiftUI Fundamentals, refreshed for iOS 26. It includes updated visuals and subtle refinements throughout, matching the Liquid Glass design that now defines Apple's latest platforms.

The framework itself hasn't changed much, and the same core principles of view composition, state flow, and layout behavior still shape how SwiftUI operates. This update focuses on keeping everything accurate and aligned with iOS 26, with a few explanations refined along the way.

If you already own the book, you can get the October 2025 edition from the book website now. If you haven't accessed it for a while and got signed out, you can get a fresh link sent to your email address by filling in the request access form.

If you haven't checked out the book yet and want to deepen your understanding of SwiftUI, this is a great place to start. I wrote SwiftUI Fundamentals to help developers build a clear mental model of how everything in SwiftUI fits together and why it works the way it does, drawing on my experience contributing to the framework at Apple.


Breve version 1.1 and Halloween specials

At the end of September I released a new app Breve: Coffee Recipes, and I shared some technical insights from building it in the last newsletter issue. If you missed it or would like to read a slightly more detailed version, you can take a look at my blog post - Introducing Breve: an arty coffee app built for iOS 26.

This month I had to push a new update after spotting an issue in the iOS 26.1 beta. In the first version of Breve, I used the newly introduced tab view bottom accessory to display countdown timers, so an active timer would always be visible above the tab bar. With logic similar to the example below, the accessory view only appeared when there was an active timer on iOS 26.0. On iOS 26.1, however, it became visible at all times, even when empty.

TabView {
    ...
}
.tabViewBottomAccessory {
    if let timer = timerViewModel.activeTimer {
        CountdownTimerView(timer: timer)
    }
}
Coffee drink collections in Breve on iPad and a Cortado recipe on iPhone

Breve v1 on iOS 26.1 with an active timer and without

The only way to avoid this would be to use a conditional statement showing a tab view with the tabViewBottomAccessory() applied when there is an active timer, and a tab view without the modifier otherwise. But I didn't like the idea of re-rendering the entire view hierarchy every time a timer is started or stopped, so I decided to implement my own custom Liquid Glass timer view that doesn't rely on the tab view bottom accessory.

I used the glassEffect() modifier with the regular variant, since it makes the content more readable than the clear glass used in the bottom accessory. I also made it interactive, as users can tap the timer from anywhere in the app to navigate to the recipe it was set for. To keep the timer view always visible above the tab bar, I placed it inside the bottom safe area bar. The only inconvenience with this approach is that I have to make sure this code is applied to every view where the timer should appear, so I encapsulated it into a custom view modifier.

struct TimerBar: ViewModifier {
    @Environment(TimerViewModel.self)
    private var timerViewModel
    
    func body(content: Content) -> some View {
        content
            .safeAreaBar(edge: .bottom) {
                if let timer = timerViewModel.activeTimer {
                    CountdownTimer(timer: timer)
                        .glassEffect(.regular.interactive())
                }
            }
    }
}
Coffee drink collections in Breve on iPad and a Cortado recipe on iPhone

Breve v1.1 on iOS 26.1 with an active timer and without

I also used this opportunity to make a few small refinements in the app based on early user feedback. I added a setting to switch to precise measurements in recipes for those who prefer to weigh everything, and implemented a shimmering animation for image placeholders to make it clearer that loading is in progress when the app is first opened on a slow network connection.

To support my Halloween in-app event, I added deep linking so the event could open the Halloween Specials category directly. The event is now live on the App Store and will run until next week, in case you'd like to have a bit of fun and make some spooky Halloween coffee drinks: Breve - Halloween Specials.

Coffee drink collections in Breve on iPad and a Cortado recipe on iPhone

Halloween specials in Breve


Recent blog articles and tips

While updating my SwiftUI Fundamentals book for iOS 26 and reviewing all the code examples, I noticed a few subtle changes that haven't been talked about much. On iOS 26, SwiftUI now shows both the title and icon in swipe action buttons by default. Previously, a button that included both would only display the icon when placed inside a swipe action. I've shared more details and a way to restore the previous icon-only appearance if needed in my post: Show icons only in SwiftUI swipe actions on iOS 26.

Another small but exciting update is the addition of a close button role for dismissing sheets and full-screen covers. It's designed for buttons that dismiss informational views and automatically shows the standard close icon without needing a custom label. Check out the Add a Close button to SwiftUI modals on iOS 26 tip on my blog to learn more.

I also shared a tip on how to avoid unnecessary text truncation, that appears to be more common on iOS 26, by applying the fixedSize() modifier to Text views. I noticed the issue when testing Breve with Dynamic Type and wrote a short blog post with my solution: Avoiding text truncation in SwiftUI with Dynamic Type.

And finally, I've been exploring ways to customize scroll behavior in SwiftUI using scrollTargetBehavior(). It's been available since iOS 17, but I only used it in practice for the first time to implement view-aligned snapping for horizontal carousels in Breve. With this API, it's possible to achieve both paging and view-aligned snapping, though there are a few details to keep in mind. I wrote a post documenting what I learned: ScrollView snapping in SwiftUI.


Discounts

Every month, I share exclusive, limited-time offers on my books with email newsletter subscribers. Sign up so you don’t miss future newsletter issues and can take advantage of upcoming discounts!


Subscribe so you don’t miss future issues!

Invalid email address

Unexpected server error

Subscribed!

We take your privacy seriously and will never share your details with third parties.

You can unsubscribe anytime using the link in our emails.

Newsletter RSS feed