All Articles
CategorySwiftUI
Reading Time
9 min read
Published
2026-10-15
Word Count
1,672words

Grab a coffee — this one is a deep dive!

SwiftUI iOS 26 Showcase: sixteen demos and a test that had to learn to fail

Summary

How SwiftUI iOS 26 Showcase keeps sixteen iOS 26 API demos honest with a catalog, compiled README examples and a rendering test that can fail.

  • Reading the documentation tells you the signatures.
  • Every demo is a case of ShowcaseDemo with its metadata: title, summary, SF Symbol, category, the APIs it shows and the platforms it runs on.
  • Add the package in Xcode with File › Add Package Dependencies… and the URL https://github.com/muhittincamdali/SwiftUI-iOS26-Showcase.git, keeping the default rule from 2.0.0.
  • Every screen has controls to try the API's options and lists the SDK symbols it uses.
SwiftUI iOS 26 Showcase: sixteen demos and a test that had to learn to fail

Table of Contents


The problem

iOS 26 and macOS 26 brought a long list of new SwiftUI APIs: Liquid Glass, tab bar minimizing,

toolbar spacers, scroll edge effects, a rich text TextEditor, a native WebView, Chart3D,

SF Symbol draw effects, the @Animatable macro and the on-device Foundation Models framework.

Reading the documentation tells you the signatures. It does not show you what Glass.clear looks

like next to Glass.regular, or what a tab bar accessory does when the bar minimizes.

SwiftUI iOS 26 Showcase is a Swift

package with sixteen small screens, each built around one group of these APIs. Every screen has

controls to try the API's options and lists the SDK symbols it uses. You can run the whole

gallery, or put a single screen into your own app.

The package did not start in this shape. The repository was opened in February 2026. The 2.0.0

changelog says what it looked like before the rebuild: from June 2026 it held only

placeholders — "enterprise" helpers (a circuit breaker, a retry policy, an event bus) unrelated

to SwiftUI, a gallery whose only behaviour was a print call, and a test file that referenced

types that did not exist, so the tests never compiled. The old CI workflow ignored test

failures, so it still showed green. Version 2.0.0, released on 14 October 2026 through

PR #3, replaced all of it.

Because the earlier public types were removed, it is a new major version.

That history set the main goal for the rebuild: a showcase is only useful if what it claims is

true, and the claims have to be checked by something other than the author's memory.

Design decisions and alternatives

One enum as the single source of truth. Every demo is a case of ShowcaseDemo with its

metadata: title, summary, SF Symbol, category, the APIs it shows and the platforms it runs on.

The gallery rows, search and the demo table in the README all come from this metadata.

ShowcaseDemoView switches over the enum to pick the view, so adding a case without a view

breaks the build. The alternative was a Demo protocol with a registry that each view adds

itself to. That puts metadata next to the view, but a forgotten registration fails silently at

run time; with the enum, the compiler finds it.

A catalog that does not import SwiftUI. ShowcaseCatalog filters demos by platform,

searches, groups by category and looks a demo up by identifier. It only imports Foundation, and

the gallery is a thin view over it, so the behaviour is tested with plain unit tests. The search

rule is simple on purpose: a query matches a demo when every word appears in its title, summary

or API list, ignoring case and diacritics. Fuzzy matching was the obvious alternative, but for

sixteen items a rule that you can state in one sentence is easier to test and to predict.

Platform differences in two layers. Two demos use APIs that do not exist on macOS:

tabBarMinimizeBehavior(_:) and listSectionIndexVisibility(_:). Their views are wrapped in

#if os(iOS), and on macOS ShowcaseDemoView shows a ContentUnavailableView instead. The

metadata marks them as iOS-only, so the macOS catalog lists the other fourteen, and

demo(withID:) returns nil for a demo that is not available on the catalog's platform. A

deep link cannot open a screen that would not work.

A small public surface. The public API is the gallery, ShowcaseDemoView, the catalog types

and three helpers that the README documents: WebAddress, RichTextFormatter and

SurfaceFunction. The sixteen demo views are internal, so they can change without a major

version. Logic that does not need a view lives in those helper types so that tests can reach it.

WebAddress, for example, accepts only http and https addresses with a host and no user

name. A comment in the source explains why the user name check matters: without it,

mailto:a@b.com would parse as user mailto on host b.com once https:// is added.

A real minimum toolchain. tabViewBottomAccessory(isEnabled:content:) is marked

@available(iOS 26.1). The tab bar demo checks #available(iOS 26.1, *) at run time, but

#available does not help when the symbol is missing from the SDK, so Xcode 26.0 cannot build

the package. The Getting Started article was changed to name Xcode 26.1 as the minimum

(commit 7ec13b4), and the README and the changelog say the same.

A real bug: the rendering test that could not fail

The most useful lesson in this repository came from a test that passed for the wrong reason.

The first rendering test, everyAvailableDemoRenders, drew each demo with ImageRenderer and

checked the image size. The size came from the frame the test set itself, so the check could not

fail. Commit `b5d727a`

records what a closer look found: 11 of 14 demo images were blank. ImageRenderer does not draw

the contents of a ScrollView, and the demo pages were laid out inside one.

The fix had two parts. First, commit ba4c342 added a seam: an environment value that turns

scrolling off, and a small view that respects it.

swift
1/// A vertical scroll view, or just its content when `demoPagesScroll` is off.
2struct DemoScrollView<Content: View>: View {
3 @Environment(\.demoPagesScroll) private var scrolls
4 @ViewBuilder let content: Content
5 
6 var body: some View {
7 if scrolls {
8 ScrollView { content }
9 } else {
10 content
11 }
12 }
13}

The default stays true, so the app behaves as before. It is a test-only concern in production

code, and the source says so in a one-line comment. The alternatives were a snapshot testing

library or UI tests, both with more dependencies and slower runs.

Second, the test was rewritten. Each demo is now rendered at 390 points wide and its natural

height, with scrolling off, and compared with a bare DemoPage that has only the same summary

and API list. The demo must be taller and must draw more non-transparent pixels. A control test

checks the measurement itself: Color.clear draws zero pixels and a line of text draws more

than zero. The commit message notes that removing the content from DemoPage makes the test

fail for every page-based demo.

Then the same question was asked of the new test, and it found a second gap. The scroll edge

demo still used a plain ScrollView, and its segmented picker sits in a safe area bar outside

the page content. The test only ever saw the picker: removing all 30 rows left the pixel count

unchanged (2b30b15). The demo moved to DemoScrollView, the row count became a static

constant, and a dedicated test now requires the page to be at least rowCount × 44 points

taller than the bare page. With the rows replaced by ForEach(0..<0) the page is 186 points

tall against a minimum of 1,482, and the test fails; with all 30 rows it is 1,866 points

(d35fd7f).

The last step was to write down what the test cannot see. ImageRenderer does not draw a List

or a WebView. The two List-based demos are left out of the rendering test, and removing the

WebView from the web view demo leaves the rendered height and pixel count unchanged (205

points, 17,890 pixels), because the address and status bars alone make the page larger

(c713b8c). That note sits next to the test, and the README states the same limits.

The lesson is plain: a green check is only worth what it can detect. The way to find out is to

break the code on purpose and watch the test fail.

Usage

Add the package in Xcode with File › Add Package Dependencies… and the URL

https://github.com/muhittincamdali/SwiftUI-iOS26-Showcase.git, keeping the default rule from

2.0.0. Then replace your app's main file with:

swift
1import SwiftUI
2import SwiftUIiOS26Showcase
3 
4@main
5struct DemoApp: App {
6 var body: some Scene {
7 WindowGroup {
8 ShowcaseGallery()
9 }
10 }
11}

To show a single demo inside your own navigation:

swift
1struct ChartScreen: View {
2 var body: some View {
3 NavigationStack {
4 ShowcaseDemoView(.chart3D)
5 }
6 }
7}

The catalog behind the gallery can be used directly, for example to build your own demo browser:

swift
1let catalog = ShowcaseCatalog(platform: .iOS)
2let matches = catalog.demos(matching: "glass button") // [.glassButtons]
3let sections = catalog.sections(matching: "symbol") // one section: Charts, Symbols & Animation
4let demo = catalog.demo(withID: "webView") // .webView

These blocks are copied verbatim into ReadmeExamplesTests.swift, where they compile and their

results are checked with #expect. A separate parameterized test reads the README and fails when

a row of the demo table does not match the metadata. At the 2.0.0 tag, swift test on macOS

runs 39 tests in 9 suites; CI also runs the tests in the iOS Simulator and builds the example

app for iOS and macOS.

Limits

  • There are no snapshot or UI tests. The rendering test answers only "did this demo draw its

own content", and the two List demos and the WebView content are outside it.

  • The scroll edge test checks height only, so rows that draw nothing but keep their 44-point

height would still pass.

  • The Foundation Models demo needs a device with Apple Intelligence turned on to send prompts,

and the web view demo needs a network connection. Neither the model call nor the page load is

tested automatically.

  • The minimum toolchain is stated as Xcode 26.1, but CI runs on the macos-26 runner image

without a version matrix, so that lower bound is not tested on its own.

  • The demo texts are English only. The README has nine translations; the app does not.
  • At the 2.0.0 tag, the Package.swift snippet in the README's Installation section still uses

branch: "main", while the quick start and the Getting Started article use 2.0.0.

  • The README roadmap has one item: demos for SwiftUI APIs that later iOS 26 updates introduce.

The code, the changelog and the tests are in the

repository, and the API reference

is on GitHub Pages.

Tags

#swiftui#ios26#liquid-glass#foundation-models#swift-testing
Muhittin Çamdalı

Muhittin Çamdalı

Senior Mobile Engineer

Senior Mobile Engineer with 12+ years of experience. I build mobile products with iOS, Flutter and React Native, working full-stack and AI-native.

iOS Development News

Weekly Swift tips, SwiftUI tricks and iOS best practices. No spam, only valuable content.

Your subscription starts when you open the link in the confirmation email and press “Confirm my subscription”. The newsletter keeps open/click statistics; you can unsubscribe anytime with one click. Privacy

Share