I'm new to SwiftUI and there's something I cannot understand and I hope someone can explain this to me. Unfortunately, none of the SwiftUI tutorials I have read or watched or found have dived this deep into the fundamental concepts.
What I'm trying to achieve:
- I'm trying to create a bunch of SwiftUI buttons which are similar to each other in some aspects and different in some other aspects. So I'm NOT looking for having ButtonA & ButtonB & ButtonC & ... and configure each of them separately. The ideal solution is to have a GeneralButton to which I can pass multiple parameters and configure it to the specific need of that instance.
- I have several presets for those buttons so I'm trying to create some sort of styling mechanism in which I can create a button using one of those predefined styles.
The approach I'm trying:
- I'm trying to create a custom
ButtonStylethat has a property which contains the type of style I need and configure the button based on that.- I also am trying to put all the required subviews (Which are not a lot) in the body of that general button and configure them based on the type of button (e.g in an icon-only button the icon is the only element in the button, there's no title, subtitle, indicator, etc)
The issue:
- I cannot access the custom body of the button from the
makeBodyfunction in the ButtonStyle protocol and hence I cannot do any customisation over subviews.
The ambiguous part:
- I checked the properties on
ButtonStyleConfigurationin order to find out how can I access the view's body, and saw that not only the body is not accessible, there is a Label property existing there statically. While it was weird to have a label there (Because a button does not necessarily needs a label! Yes it usually does but not always) Since it was a SwiftUI view I tried to cast it to the kind of view I'm trying for which I faced the following error:Cast from 'ButtonStyleConfiguration.Label' to unrelated type '[MyButtonPrefix]Button' always fails- I went a bit deeper and read the documentation for SwiftUI Button struct in general, and as can be seen below, it is designed to have a "Label" and if that cannot be inferred from the subviews it won't let you create the button:
@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *)
public struct Button<Label> : View where Label : View {
/// Creates a button that displays a custom label.
///
/// - Parameters:
/// - action: The action to perform when the user triggers the button.
/// - label: A view that describes the purpose of the button's `action`.
public init(action: @escaping () -> Void, @ViewBuilder label: () -> Label)
/// The content and behavior of the view.
public var body: some View { get }
/// The type of view representing the body of this view.
///
/// When you create a custom view, Swift infers this type from your
/// implementation of the required `body` property.
public typealias Body = some View
}
The document explicitly dictates the necessity of having the Label and the nature of SwiftUI's button being designed to show a label :
Creates a button that displays a custom label
I'm pretty sure that I'm making some serious mistake as I'm absolutely new to SwiftUI but I can't understand what's going on above and any explanation is really appreciated. All the tutorials I have went through were treating SwiftUI's Button as something that obviously has a "Label" and I haven't found anything that has provided a more general and modular perspective on creating completely custom and fully reusable button-related components in SwiftUI.