Utilize View Modifiers to write cleaner code

July 16, 2021 • 5 min read

When it comes to writing clear and concise code, there is a core foundation all developers should consider. DRY. The acronym stands for “Don’t repeat yourself.” By extrapolating code that does too many things into many smaller components, we can increase the reusability of the code and reduce the amount of time we spend writing the same thing. SwiftUI brings a new way to increase reusability by giving us View Modifiers.

Simply put a View Modifier is a modifier that you apply to a view or another view modifier, producing a different version of the original value.

Why use View Modifiers?

As developers, we want to reduce the amount of code that we write. Therefore, using something like a view modifier would be in our best interest. Not only does it help us work faster, but it can also reduce our error rate. Redundancy - check. Error reduction - check. Now, what does that mean in practice?

Let’s look at some code that you might see in a solo project where they might gleefully push to the master branch without a care in the world.

struct ContentView: View {
    
    var body: some View {
        VStack {
            Text("Header")
                .font(.largeTitle)
                .foregroundColor(.white)
                .padding()
                .background(Color.pink)
                .clipShape(RoundedRectangle(cornerRadius: 8))
            Text("Longer version of the header")
                .font(.largeTitle)
                .foregroundColor(.white)
                .padding()
                .background(Color.pink)
                .clipShape(RoundedRectangle(cornerRadius: 8))
                .multilineTextAlignment(.center)
        }
    }
}

At first glance, this code looks optimal. It does what you want: creates two Text views that each have a couple of modifiers - you were using view modifiers, and you didn’t even know about it. There is nothing wrong with the code technically; if you check the preview, it runs, and if you run the app, it builds just fine. The red flag here is that you repeated the same five lines on both Views when you could have just written it once.

View Modifiers give us the luxury of doing just that. Writing them once and reaping the rewards anytime we attach the modifier to it.

Making our first modifier

Since SwiftUI uses modifiers just about everywhere, there is an easy way to create a custom modifier built right in:

struct HeaderTitle: ViewModifier {
    func body(content: Content) -> some View {
        content
            .font(.largeTitle)
            .foregroundColor(.white)
            .padding()
            .background(Color.pink)
            .clipShape(RoundedRectangle(cornerRadius: 8))
            .multilineTextAlignment(.center)
    }
}

Notice that although only one Text view from earlier uses the .multilineTextAlignment modifier, by applying it to all of the Views that adopt our custom modifier, we don’t have to worry about including that later on in the content.

To make sure we understand what this body function is doing, let’s jump through the core concepts:

  1. Since everything in SwiftUI is a Struct, create a custom ViewModifier Struct by the name of HeaderTitle.
  2. Inside of the ViewModifier Protocol exist a ViewBuilder function that looks like this: @ViewBuilder func body(content: Self.Content) -> Self.Body
  3. This Content passed into the View is a proxy for the View that will have the modifier represented by Self applied to itself.
  4. Our content will now hold all the modifiers that our Text views had before.

That’s it! When it’s all said and done, this is all you need to have a View Modifier that you place on your Text views. We will take it a little further and sprinkle some more of that syntactical sugar on it.

Creating our modifier extension

Now in whatever file you like to place your extensions in, or if you want to add it to the end of the View Modifier structs file, you can apply for this View Extension:

extension View {
    func headerStyle() -> some View {
        self.modifier(HeaderTitle())
    }
}

By having this extension, we can make our code look like organic SwiftUI code:

Text("Header")
    .headerStyle()

So by applying this new extension to our previous views, we can make the wordy code simple to read:

struct ContentView: View {
    
    var body: some View {
        VStack {
            Text("Header")
                .headerStyle()
            Text("Longer version of the header")
                .headerStyle()
        }
    }
}

Conclusion

View Modifiers are a small example of what SwiftUI is capable of doing. Apply your View Modifiers to many different views, and if you need to extend these modifiers even further, you have that ability. The reusability of SwiftUI makes it a powerful tool in your arsenal; you just need to know how to use it. Try it with Buttons, Shapes, and even Textfields! You will have a beautiful UI with code that isn’t repeated and bloated.