You can find the official documentation here.
Also see Fucking SwiftUI (or Gosh Darn SwiftUI) for a nice “cheat sheet” and a breakdown of UIKit equivalent APIs.
Apps built fully (or mostly) with SwiftUI.
An app that documents all the SwiftUI views, shapes, protocols, scenes, property wrappers, styles and environment values found in all platforms (iOS, macOS, tvOS, watchOS).
A GUI for SwiftUI Design.
SwiftUI has a new, pretty cool, debugging utility to help you understand what is causing a view to be reevaluated.
Call
Self._printChanges()
inside the body of a view to print out the changes that have triggered the view update.
SwiftUI has been around for almost 3 years now, and during this period working with it, I’ve noticed few groups of developer mistakes (both mine and from others) that can impact its performance. In this post, we will look at these pitfalls, and their potential solutions.
When we work with SwiftUI, we can always drop down to UIKit level by using UIViewRepresentable, NSViewRepresentable or UIViewControllerRepresentable. The documentation around these protocols is still pretty sparse, and it can be hard to get them to work exactly the way we want. I tried to come up with some rules and patterns for using them.
SwiftUI get amazing updates every year. If you however have to support old OS versions, you may be unable to use the new tools, or jump through hoops to make it work.
In this post, let’s look at a semantic approach to use new, non-critical features in apps that target old OS versions.
.onAppear()
is called on DISappear instead of appearUnfortunately, .keyboardDismissMode
is not available in SwiftUI, so hacks are required:
There are many blog posts out there with similar modifiers. I think all these blog posts should come with a huge warning sign. Why is the above code problematic? Let’s look at a sample.
See Michael Tsai’s post on iOS 15 Shortcuts and SwiftUI.
SwiftUI metrics & padding changes in macOS 12 are… ‘a problem’. I’m seeing all kinds of wrong behavior across my apps, compared to macOS 11. Fixing for one will break the other, which would mean a lot of nasty if statements. I hear iOS 15 has similar issues.
Growing increasingly concerned about this critical SwiftUI Button bug that breaks trackpad/click focus on iPadOS 15 + macOS Monterey. […] Oh wow, this bug is actually present in the Shortcuts app too (created in SwiftUI w/ iOS 15?)
We’re in ‘year 3’ of SwiftUI, and my base advice remains unchanged — it is great for auxiliary non-critical UI layouts (inspector sidebars, settings windows, and panels), watchOS apps, and rapid prototyping. Beyond that, it just does not meet the bar for complex, reliable apps
Introspect underlying UIKit components from SwiftUI
When working on any kind of app or system, it’s almost guaranteed that we’ll need to debug our code at one point or another. For example in order to reproduce a bug that’s been reported to us by either a tester or a user, to track down a race condition or some other source of ambiguity within our logic, or to fix a view that’s not being rendered correctly.
But what if we wanted to know more about that view? In this article, let’s explore how we can do so.
Setting a random background color is a great way to detect an accidental SwiftUI loop. The tricky part is understanding what triggers the loop tho.
See also, David Smiths’s “Random Border Trick”:
A little trick I found super useful was to set the border of each of the various views involved to a random color and then it see what borders change whenever the view rebuilds. This helped me countless times to determine where in the view tree the problem was.
The clipped() modifier in SwiftUI clips a view to its bounds, hiding any out-of-bounds content. But note that clipping doesn’t affect hit testing; the clipped view can still receive taps/clicks outside the visible area.
For the most part SwiftUI’s layout system is intuitive to use, letting you achieve what you want with a little bit of experimentation. However, sometimes you encounter behaviors that are hard to reason about without a deeper understanding of the underlying implementation.
A few days ago we tweeted a series of layout quizzes for SwiftUI’s LazyVGrid to highlight some of the less obvious behaviors. In this post we’ll take a look at all three quiz questions and explain why the grid lays out its contents in the way it does.
Interestingly, we were not the only ones struggling to understand the behavior of grids: none of the most popular quiz answers were correct!
Each view undergoes a series of events from its birth to its death, which is referred to as a lifecycle. Understanding it is essential when building apps in SwiftUI. In this article, we will explore the three phases of the SwiftUI view lifecycle.
For the longest time, iOS developers have used AppDelegates as the main entry point for their applications. With the launch of SwiftUI2 at WWDC 2020, Apple has introduced a new application life cycle that (almost) completely does away with AppDelegate, making way for a DSL-like approach.
In this article, I will discuss why this change was introduced, and how you can make use of the new life cycle in new or existing apps.
As of WWDC 2021, SwiftUI supports bindings for list elements.
[…]
But how does it work?
In SwiftUI, identity holds the key to understanding how the rendering system works. A View’s identity tells SwiftUI which of that View’s values correspond to the same rendered view over time. This identity has strong implications for correctness, performance, and as we will see, transitions.
A beginner friendly article on view identity with an intro about Swift UI in general.
This is a large part of why I suggest creating an abstraction layer for Core Data. An abstraction layer allows me to hide the nitty gritty details of data mutation and persistence from the parts of the app that deal with displaying that data in the UI.
An initial approach might suggest that creating a Core Data abstraction layer requires foregoing all the nice affordances we have for quickly and expressively extracting information from the persistent store. Not so! The setup we’ll be going over allows me to have the abstraction layer while still using cool things (like property wrappers) for retrieving data.
When you’ve added Core Data to your SwiftUI project and you have some data stored in your database, the next hurdle is to somehow fetch that data from your Core Data store and present it to the user.
The easiest way to see how Core Data works with SwiftUI is by creating a new SwiftUI project and selecting the Use Core Data checkmark. Xcode will generate a working example that we can try out and review immediately.
In iOS 15, it’s easier to dynamically configure a Core Data fetch request for use with SwiftUI.
This blog will take a look at a basic setup for a multi-platform SwiftUI app.
This year, however, entire apps can now be defined directly using SwiftUI, thanks to a few new additions to its API.
Native support for grids in SwiftUI is finally here. This is made possible by two new views. These are LazyVGrid and LazyHGrid.
SwiftUI views layout depends on each view state. This state is composed of a mix of internal properties, external values coming from the environment, etc.
While this is great and can save us hundreds of hours, sometimes we want to make our UI declarations even more adaptive: in this article, let’s see how we can do so.
The SwiftUI ViewThatFits view, introduced in iOS 16, makes it a lot simpler to build layouts that adapt to make best use of the available space.
Here’s a first draft of a decision tree for how to define your SwiftUI properties…
What separates SwiftUI from Apple’s previous UI frameworks isn’t just how views and other UI components are defined, but also how view-level state is managed throughout an app that uses it.
[…]
This week, let’s take a closer look at each of those property wrappers, how they relate to each other, and how they make up different parts of SwiftUI’s overall state management system.
This week we will learn all about the new Toolbar API.
We are talking about a new extension to the View protocol, the .matchedGeometryEffect() modifier. On its own, it’s good enough, but in combination with other techniques we learned already (custom transitions and animatable modifiers), it becomes even better. It is an essential skill to put in your SwiftUI toolkit.
SwiftUI now ships with a new, built-in modifier that makes it really easy to automatically generate a placeholder for any view.
.redacted
effectsWith the recent release of Xcode 12 we’ve gained a new
.redacted(reason:)
SwiftUI modifier.
In this article, let’s explore this view beyond the basics.
And now that SwiftUI also supports user activities and the scene delegates are gone, there’s even more change. A good time then, for a new article.
Now with the new SwiftUI capabilities, we can collapse content with DisclosureGroup. Let’s see how we could use it in various ways.
In this article, we will go through all important parts related to the implementation of transitions in SwiftUI - from the very basics to more advanced techniques.
However, if we start exploring SwiftUI’s various APIs and conventions a bit further, it turns out that there are a number of tools and techniques that we can use to create a clean separation between our view hierarchy, its styles, and the components that we’re looking to reuse across a given project.
One of the most important aspects of that kind of asynchronous work, at least when it comes to building UI-based apps, is figuring out how to reliably update our various views according to the current state of the background operations that we’ll perform. So this week, let’s take a look at a few different options on how to do just that when building views using SwiftUI.
Before we begin, let’s put it right there: SwiftUI is not prepared to handle attributed strings easily. With that out of the way, let’s see the best approaches to fill that void and the limitations or problems we will find along the way.
This week, we will discuss the new keyboardShortcut modifier, which allows us to assign a shortcut to any interacting view.
One of these new APIs was the focus management API that we can use on iOS, macOS, tvOS, and watchOS. This week we will talk about SwiftUI functionality that allows us to manage the focus in our apps.
So, in this article, let’s take a look at two core techniques that can help us avoid AnyView while still enabling us to work with multiple view types in very dynamic ways.
SwiftUI uses property wrappers to understand how we create and store data in our views, but if you need helping choosing which property wrapper is right for you I’ve made a tool to help. To find the right property wrapper for you, answer the questions below.
At first blush, this looks fine – the view displays, and property within the nested view is shown as you’d expect; so what’s the problem? The issue is when you update that nested element’s property, even though it’s listed as @Published, the change doesn’t propagate to the view.
Here’s my quick guide to creating your own custom SwiftUI environment values for things like global app settings.
SwiftUI previews allow you to look at your SwiftUI views inside Xcode without running the app in the simulator. You can also preview UIKit views and controllers by wrapping them in SwiftUI. Today we will learn about all the powerful features of previews in Xcode.
How can you scale other metrics, like spacing, as the dynamic type content size changes? In iOS 14, SwiftUI gained the @ScaledMetric property wrapper that can scale any numeric value.
In UIKit and AppKit, a UISplitViewController and a NSSplitViewController would be the necessary classes for building that functionality. In SwiftUI things are different though; a NavigationView with a couple of List views do the job in a much simpler fashion. The only requirement is to follow certain steps in the proper order.
…in this article, let’s review all environment values that SwiftUI offers.
The TextField element of the SwiftUI framework does not have such a feature built-in, so you’d have to build your own solution for that. In this article I want to show how to accomplish a simple clear button inside a SwiftUI TextField element.
This article will explore how to render text with color gradients.
I’ve had a few situations in SwiftUI where I only want things to fire once and initially. At face value, this seems like a job for either
.onAppear
or the more nascent.task
.
Michael Tsai roundup.