Creating BaseView class in SwiftUI Creating BaseView class in SwiftUI swift swift

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:

BaseView screen example