A few months ago, I shared my notes and resources for learning about compilers and LLVM. It turned out to be pretty popular and folks seemed to find it useful. So I decided to do it again, but this time for SwiftUI. However, unlike learning about compilers and LLVM, I am not declaring bankruptcy with learning SwiftUI. While I have still not written a single line of SwiftUI code, I know I eventually will.
* * *
I have deliberately avoided SwiftUI for a few reasons. Most importantly, I am extremely productive in UIKit and my top priority lately has been getting shit done. While I understand that one of the benefits and goals of SwiftUI is actually to improve productivity (ironically), I do not have time to deal with its bugs and missing features, or implementing workarounds. If I know I am going to need to use the escape hatch back to UIKit, I might as well avoid the trouble altogether. I know it is getting better, and will undoubtedly improve more at WWDC this year. But the other main issue is backwards compatibility. My current understanding is that SwiftUI on iOS 13 is quite a painful experience. As long as I am working on projects that require iOS 12 or iOS 13 support, SwiftUI simply is not worth the trouble. But, I digress.
* * *
Despite not yet using SwiftUI, I do want to. And I know that eventually, I will need to. That is why I have been reading blog posts and keeping notes. All of these notes live in my public TIL repo. Side note: it has been really great to move all of this content out of my OmniFocus projects and into these public notes. It is a better organizational practice for me (I now just link to these notes in OmniFocus) and it makes them available for others to learn, too. A win-win. You can find the nicely rendered HTML page here.
Also, if you have resources you would like to share, pull requests are welcome.
For the purposes of this post, I am going to reproduce the current notes I have below. However, if you want to stay updated you should watch the repo on GitHub for changes, or bookmark this page. I intend to keep updating these notes.
* * *
My notes on SwiftUI
You can find the official documentation here.
Apps built fully (or mostly) with SwiftUI.
Known Issues + Workarounds
- Apple Documentation and SwiftUI for Mac
- The State of SwiftUI
- Self-Sizing UITableView Cells with SwiftUI
- Fixing keyboardShortcut in SwiftUI
- Supporting Both Tap and Long Press on a Button in SwiftUI
- Disabling Keyboard Avoidance in SwiftUI’s UIHostingController
- Poor performance for macOS apps
- Keyboard Navigation in SwiftUI
- iOS 14
.onAppear()is called on DISappear instead of appear
- The SwiftUI Experiment - Retrospective
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.
Behind the scenes: How SwiftUI works
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.
Working with Core 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.
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.
General “How To”
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.
With the recent release of Xcode 12 we’ve gained a new
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.