How to make SwiftUI modifiers safer to use with @warn_unqualified_access
How to make SwiftUI modifiers safer to use with @warn_unqualified_access 관련
Updated for Xcode 15
Every SwiftUI makes the same mistake at some point, and sadly it’s something you’ll do more than once: rather than writing .someModifier()
you write someModifier()
, and it causes your app to completely freeze or crash with EXC_BAD_ACCESS
.
First I’ll show you the how to solve the problem, then I’ll explain what the underlying problem is. The solution is to use Swift’s @warn_unqualified_access
attribute, which means you can’t access properties or methods without using a variable name or similar.
For example, if we had a titleStyle()
method that added a bunch of modifiers to a view to make it matching a custom theme, we’d use @warn_unqualified_access
before the method signature, like this:
extension View {
@warn_unqualified_access
func titleStyle() -> some View {
self
.font(.largeTitle)
.fontWeight(.black)
.padding()
.background(.blue)
.foregroundStyle(.white)
.cornerRadius(10)
}
}
When we use that, we’d write the same SwiftUI code we always did:
struct ContentView: View {
var body: some View {
Text("Welcome")
.titleStyle()
}
}
That works exactly as expected – the extra attribute hasn’t made the method behave differently at all in normal circumstances.
However, take a look at this code:
struct ContentView: View {
var body: some View {
Text("Welcome")
titleStyle()
}
}
That’s subtly different: I removed the dot before titleStyle()
, which is an unqualified access – I haven’t said where I’m calling titleStyle()
, so SwiftUI assumes I’m actually calling it on ContentView
. This means it’s actually calling self.padding()
, so we have an infinitely recursive view and ultimately a crash.
Sadly, SwiftUI doesn’t use @warn_unqualified_access
with its own modifiers, but you can at least add it for the custom ones you build.