Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

ios

swiftui

I know tons of people already thought about this, however I could't find any good answer on Stackoverflow or a good tutorial that purely talk about this even on some famous channels in Youtube.

My question is very simple:

In SwiftUI we may do tons of time 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 absolutely don't want to write .padding(EdgeInsets(top: 3, leading: 3, bottom: 3, trailing: 3)).background(Color.blue).cornerRadius(5) for every "Text(...)" or other like "Button" or any other SwiftUI component. we do want to wrap the .padding(EdgeInsets(top: 3, leading: 3, bottom: 3, trailing: 3)).background(Color.blue).cornerRadius(5) in some kind of methods or somewhere else. I know how to do it in UIKit, but the question is how do we do that since SwiftUI is a declarative way of build GUIs?

Thanks.

like image 690
Invincible_Pain Avatar asked Dec 14 '19 05:12

Invincible_Pain


2 Answers

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

like image 57
Asperi Avatar answered Sep 25 '22 02:09

Asperi


I would create every component as a view, instead of an extension. That way you can always preview the component and have a central repository of 'reusable' components:

struct customText : View {

 let text: String

 var body: some View {

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

Append a preview to the above and you can always view exactly what your text will look like in the preview canvas, making future edits easier.

And to use:

customText(text: "Hello World")

You can still add modifiers to its use. You can then have a single source of views which can be used throughout your app (different text types, buttons, etc).

like image 23
dot3 Avatar answered Sep 24 '22 02:09

dot3