Creating BaseView class in SwiftUI
Usually you want to either have a common behaviour or a common style.
1) To have a common behaviour: composition with generics
Let's say we need to create a BgView
which is a View
with a full screen image as background. We want to reuse BgView
whenever we want. You can design this situation this way:
struct BgView<Content>: View where Content: View { private let bgImage = Image.init(systemName: "m.circle.fill") let content: Content var body : some View { ZStack { bgImage .resizable() .opacity(0.2) content } }}
You can use BgView
wherever you need it and you can pass it all the content you want.
//1struct ContentView: View { var body: some View { BgView(content: Text("Hello!")) }}//2struct ContentView: View { var body: some View { BgView(content: VStack { Text("Hello!") Button(action: { print("Clicked") }) { Text("Click me") } } ) }}
2) To have a common behaviour: composition with @ViewBuilder closures
This is probably the Apple preferred way to do things considering all the SwiftUI APIs. Let's try to design the example above in this different way
struct BgView<Content>: View where Content: View { private let bgImage = Image.init(systemName: "m.circle.fill") private let content: Content public init(@ViewBuilder content: () -> Content) { self.content = content() } var body : some View { ZStack { bgImage .resizable() .opacity(0.2) content } }}struct ContentView: View { var body: some View { BgView { Text("Hello!") } }}
This way you can use BgView
the same way you use a VStack
or List
or whatever.
3) To have a common style: create a view modifier
struct MyButtonStyle: ViewModifier { func body(content: Content) -> some View { content .padding() .background(Color.red) .foregroundColor(Color.white) .font(.largeTitle) .cornerRadius(10) .shadow(radius: 3) }}struct ContentView: View { var body: some View { VStack(spacing: 20) { Button(action: { print("Button1 clicked") }) { Text("Button 1") } .modifier(MyButtonStyle()) Button(action: { print("Button2 clicked") }) { Text("Button 2") } .modifier(MyButtonStyle()) Button(action: { print("Button3 clicked") }) { Text("Button 3") } .modifier(MyButtonStyle()) } }}
These are just examples but usually you'll find yourself using one of the above design styles to do things.
EDIT: a very useful link about @functionBuilder (and therefore about @ViewBuilder) https://blog.vihan.org/swift-function-builders/
I got a idea about how to create a BaseView in SwiftUI for common usage in other screen
By the wayStep .1 create ViewModifier
struct BaseScene: ViewModifier { /// Scene Title var screenTitle: String func body(content: Content) -> some View { VStack { HStack { Spacer() Text(screenTitle) .font(.title) .foregroundColor(.white) Spacer() }.padding() .background(Color.blue.opacity(0.8)) content } }}
Step .2 Use that ViewModifer in View
struct BaseSceneView: View { var body: some View { VStack { Spacer() Text("Home screen") .font(.title) Spacer() } .modifier(BaseScene(screenTitle: "Screen Title")) }}struct BaseSceneView_Previews: PreviewProvider { static var previews: some View { Group { BaseSceneView() } }}
Your Output be like: