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
Use
ViewModifier
for that, e.g.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 orViewModifier
structs the more efficient SwiftUI will run because it will have tighter invalidation (when its dependency tracking decides something has changed requiring a call tobody
)Those
View
struct properties in your code should belet
because this struct is immutable.ViewModifier
is not applicable for all of the cases you have.You can use
ViewModifier
only when you need to modify yourcontent: Content
. Note that you cannot change any property inside theContent
(e.g.content.iconName
) when you adopt theViewModifier
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
)