❌

Reading view

SwiftUI Toolbars

Natalia Panferova:

I thought it would be useful to have a single reference for the different ways we can style the toolbar in SwiftUI on macOS 26.

Phil Zakharchenko:

The toolbar id creates a stable customization domain, and each item id gives the framework something stable to persist when the user adds, removes, or reorders controls. This identifiability of toolbar items is a requirement for customization. Under the hood, when SwiftUI inevitably bridges your toolbar contents to NSToolbar, these identifiers will be directly translated to the NSToolbarItem’s itemIdentifiers.

As we continue the migration to a customizable toolbar, we are likely to encounter a few surprises related to this model.

[…]

After a closer inspection, and perhaps a few minutes of digging through the documentation, we come to the bleak realization: there is no customizable ToolbarItemGroup API.

[…]

The regular toolbar model and the customizable toolbar model overlap, but they are not interchangeable. You cannot give a ToolbarItemGroup an id, and you cannot place one directly inside toolbar(id:content:).

Majid Jabrayilov:

Let’s take a look at another example. This one is a bit tricky, because on macOS, you will get Action 1 in the top trailing position and the whole group of actions centered in the navigation bar. On iOS, you will get Action 1 pinned to trailing and all other items collapsed.

[…]

The final addition to the Toolbar API is the toolbarMinimizeBehavior view modifier allowing us to minimize toolbars while scrolling up or down. You can minimize tab, bottom, window and navigation bars with it.

With new modifiers SwiftUI gives us a much better balance between system-driven adaptation and explicit control. We can now decide which actions are more important, which items should always stay visible, which groups should intentionally live in the overflow menu, and how toolbars should react to scrolling.

Natalia Panferova:

iOS 27 includes a few smaller additions that make toolbar content easier to configure.

We can remove the default padding around an item whose content should extend to its edges with contentMarginsRemoved(_:)[…]

[…]

The status bar is now represented by ToolbarPlacement.statusBar, so its visibility can be controlled through the same toolbar API as other bars[…]

[…]

ForEach now conforms to ToolbarContent, which means we can generate toolbar items directly from a collection[…]

Natascha Fadeeva:

Together, the toolbar APIs let us express the importance of each action while SwiftUI continues to handle the toolbar’s layout across different sizes.

Previously:

  •  

TipKit for the Real World

Craig Hockenberry:

Then, when you look at the sample code, it’s all SwiftUI. At least the sample compiles and runs because it uses a completely different syntax than what was shown at WWDC.

[…]

Eventually I stumbled upon TipUIPopoverViewController which inherits from UIViewController. That should work! […] But it didn’t: the close button on the popover didn’t work.

[…]

Until you realize that any changes you make are stored in a SQLite database, debugging is very confusing. It’s also easy for your own state to get out-of-sync with the Tip state: there is not a single source of truth.

[…]

Unfortunately, that sample code doesn’t scale well. If you have a view with multiple tips, you’re going to be littering your code with tip instances, observation tasks, and popover controllers. It’s a mess and a clear sign that the TipKit developers didn’t think much about UIKit.

Fatbobman:

In the previous article, we introduced the basic usage of TipKit. In this article, we will discuss some advanced topics related to TipKit, such as how to fully customize Tip views (not using TipView and popoverTip), how to use TipKit with UIKit, and how TipKit can share data across different applications, as well as how to reuse Tip declaration code. Additionally, we will attempt to address some common questions and concerns about TipKit.

Previously:

  •  

Swift 6.4: Warning for Weak Captures Within Nested Closures

John Sundell:

New in Swift 6.4 […] is a warning which is emitted when a nested closure performs a weak capture while the parent closure implicitly captures that object as a strong reference.

At first glance, that new diagnostic could be a bit puzzling, since it might seem unnecessary to have to specify such a weak capture twice (or, alternatively, move it to the parent closure’s capture list), but it turns out that it’s an incredibly useful new warning that can help us avoid a quite common kind of memory management bug.

[…]

Finally, in situations where capturing self strongly doesn’t actually lead to a retain cycle, we can silence the new warning for nested weak captures by explicitly adding self to the outer closure’s capture list, such as when creating a Task within the following example[…]

Previously:

  •  

Ending the Golden Era for Backward-Compatible Apps

Matthias Gansrigler-Hrad:

I don’t appreciate being forced by Xcode 27 to drop support for macOS 10.13-11.0. It’s my decision which OSes I want to support, not Apple’s. Yes, I can keep Xcode 26 around until submissions require Xcode 27, but what then?

Originally, Xcode 27 was documented as supporting Big Sur on Intel Macs, but now the earliest is Monterey.

I’m frustrated, too, but it’s more honest than the recent releases that claimed to support deployment on older macOS versions when Apple clearly hadn’t tested that it actually worked. I filed bugs, and Apple kept responding that they’d fixed it, when they hadn’t.

Using old versions of Xcode isn’t a great solution because they aren’t supported on Golden Gate. Swift also makes it more difficult to call newer APIs when using an older SDK. You can’t just copy/paste a method prototype or constant value and conditionally use it when running on a newer OS.

Ighor July:

I eventually found a hidden workaround that changes the errors back into warnings. That is good news, but it does not make the concern disappear. The setting is undocumented, absent from the normal Xcode interface, and currently being tested only in a beta toolchain. The larger question is what Apple intends to enforce when Xcode 27 is final and, later, when App Store submission requirements move to its SDKs.

[…]

Apple’s current Xcode system requirements list Xcode 26 with deployment targets beginning at iOS 15 and macOS 11. Yet developers have been able to enter older targets manually. In an Apple Developer Forums discussion about Xcode 26, an Apple product manager explained that the published deployment target range is aligned with simulator support and on-device debugging. The accepted answer confirms that an iOS 13 target can still build even though it falls below the range in Apple’s table.

My own tests went further. Xcode 26.5 compiled a project targeting iOS 9.0. It warned that the target was older than the supported range, but the build succeeded. On macOS, I have compiled current apps with deployment targets as old as macOS 10.9. Xcode warned me, but it still produced working applications.

[…]

For iOS and iPadOS, staying on Xcode 26 is not a lasting option. Apple has repeatedly made a current Xcode and SDK mandatory for new App Store submissions. […] If any one of those conditions fails, iOS and iPadOS developers will have no normal App Store path for publishing new updates that still support versions older than 15.

Previously:

Update (2026-09-07): Léo Natan:

Just want to remind you guys that if you move to Xcode 27, the only “officially” supported and sanction Xcode for GG, UIDesignRequiresCompatibility is no longer respected across the 27 OSes (apps built with older Xcodes still are). So you might suddenly find out you have a lot of work ahead of you, adding support for the dreaded Glass. And 27 Glass is not the same as 26 Glass. That can be an issue if you skipped 26 altogether but still want to support it.

Previously:

Update (2026-09-11): Nick Lockwood:

I mostly ignored the Xcode 27 betas (mainly due to the barely-usable Device Hub) so I didn’t realize the passive-aggressive prompts to drop support for iOS < 15 that you get when submitting apps is being backed up by Xcode 27 refusing to compile apps at all unless you bump the deployment target 😧

  •  
❌