iosswiftswiftui

In SwiftUI, how can we reuse a set of modifiers or make them into a kind of component to not repeatedly call them?


In SwiftUI we may have many pieces of code like this:

Text("Hello World")
  .padding(EdgeInsets(top: 3, leading: 3, bottom: 3, trailing: 3))
  .background(Color.blue)
  .cornerRadius(5)

However, as you or any other very experienced and professional developers may aware, we want to stay DRY and absolutely don't want to re-write the modifiers:

.padding(EdgeInsets(top: 3, leading: 3, bottom: 3, trailing: 3))
.background(Color.blue)
.cornerRadius(5)

for every Text(...) or Button or any other SwiftUI component.

It would be better to wrap the:

.padding(EdgeInsets(top: 3, leading: 3, bottom: 3, trailing: 3))
.background(Color.blue)
.cornerRadius(5)

in some kind of method or reusable component. I know how to do it in UIKit, but the question is how do we do that in SwiftUI's declarative way to build GUIs?


Solution

  • Here is how it is usually done with custom ViewModifier, plus depicts example of how it could be configured via parameters:

    struct MyTextModifier: ViewModifier {
        let corner: CGFloat
        func body(content: Content) -> some View {
            content
                .padding(EdgeInsets(top: 3, leading: 3, bottom: 3, trailing: 3))
                .background(Color.blue)
                .cornerRadius(corner)
        }
    }
    
    extension View {
        func configured(with radius: CGFloat = 5) -> some View {
            self.modifier(MyTextModifier(corner: radius))
        }
    }
    
    struct MyTextModifier_Previews: PreviewProvider {
        static var previews: some View {
            Text("Hello World")
                .configured()
        }
    }
    

    Tested with Xcode 11.2, iOS 13.2