skip to Main Content

SwiftUI makes a pervasive usage of the Builder pattern described here, providing a lot of custom modifiers to allow optional styling of your components. One of the reasons for using this pattern is that it allows you to write simple constructors.

But how to configure properties of view with more than 10 properties. Obviously we can use model where we can wrap all properties inside struct/class. But some times it will add more overhead at call site need to create model to configure a single property . Solution to avoid this is definitely builder pattern .

Does below approach cause any performance issues w.r.t view refresh or lifetime.

public struct MyButton<TextContent: View, IconContent: View>: View {

    private var text: String?
    private var accessibilityText:  String?

    private var size: MyButtonSize  = .regular
    private var iconName: MyIconName?
    private var iconPosition: MyButtonIconPosition = .leading
    private var inverse: Bool = false
    private var disabled: Bool = false
    private var variant: MyButtonVariant = .primary

     public var body: some View { ...}

}

public extension MyButton {
    ///  sets the variant of the button
    func variant( _ variant: MyButtonVariant)-> MyButton {
        var v = self
        v.variant = variant
        return v
    }
    /// sets the size of the button.
    func size( _ size: MyButtonSize) -> MyButton {
        var view = self
        view.size = size
        return view
    }
    /// sets the icon and icon position on button.
    func icon( _ name: MyIconName?, position: MyButtonIconPosition = .leading) -> MyButton {
        var view = self
        view.iconName = name
        view.iconPosition = position
        return view
    }

    // to disable button.
    func isDisabled(_ disabled: Bool) -> MyButton {
        var view = self
        view.disabled = disabled
        return view
    }
}


2

Answers


  1. Use ViewModifier for that, e.g.

    struct BorderedCaption: ViewModifier {
        func body(content: Content) -> some View {
            content
                .font(.caption2)
                .padding(10)
                .overlay(
                    RoundedRectangle(cornerRadius: 15)
                        .stroke(lineWidth: 1)
                )
                .foregroundColor(Color.blue)
        }
    }
    

    And there is no overhead in creating structs because they are value types on the memory stack, e.g. like how wouldn’t worry about making an Int. The more you break up your view data into small View structs or ViewModifier structs the more efficient SwiftUI will run because it will have tighter invalidation (when its dependency tracking decides something has changed requiring a call to body)

    Those View struct properties in your code should be let because this struct is immutable.

    Login or Signup to reply.
  2. ViewModifier is not applicable for all of the cases you have.

    You can use ViewModifier only when you need to modify your content: Content. Note that you cannot change any property inside the Content (e.g. content.iconName) when you adopt the ViewModifier approach.

    You are doing it correct in your use cases. As I see you change internal properties such as view.iconName etc.

    There should not be any performance issue with your approach though each time you are making a new value type object. Because as structs are value type however you modify your value type view it will eventually create another new view.

    I also have created much complex views using builder pattern with almost the same approach you did. You can check this out: https://github.com/MahiAlJawad/CustomButtonBuilderPatternModifier-SwiftUI (You cannot make anything with only ViewModifier)

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search