Khawar
Khawar

Reputation: 9251

SwiftUI | How to override life cycle methods like viewWillAppear

In my existing app, there are few UI configurations like setting up a custom navigation bar, setting a full-screen background images and some more, on all view controllers. For this purpose, configurations are made in a base view controller in viewWillAppear, all view controllers and inherited from it. So configurations are made without doing anything in child view controllers

How to achieve a similar implementation using SwiftUI?

SwiftUI provides onAppear() & onDisappear() methods on View, which is Struct and doesn't support inheritance. If I make extensions methods or protocol, I have to call methods from all Views.

Any help is appreciated...

Upvotes: 1

Views: 2080

Answers (1)

rob mayoff
rob mayoff

Reputation: 385970

Make your own container view. You can use @ViewBuilder to make your view behave like VStack and HStack where it takes a content closure full of subviews.

For example, here's a custom container that gives the main content a pink background, and puts a toolbar under it:

import SwiftUI

struct CustomContainer<Content: View>: View {
    init(@ViewBuilder content: () -> Content) {
        self.content = content()
    }

    let content: Content

    var body: some View {
        VStack(spacing: 0) {
            content
                .frame(maxWidth: .infinity, maxHeight: .infinity)
                .background(Color(hue: 0, saturation: 0.3, brightness: 1))
            Toolbar()
        }
    }
}

struct Toolbar: View {
    var body: some View {
        HStack {
            Spacer()
            button("person.3.fill")
            Spacer()
            button("printer.fill")
            Spacer()
            button("heart.fill")
            Spacer()
            button("bubble.left.fill")
            Spacer()
        } //
            .frame(height: 44)
    }

    private func button(_ name: String) -> some View {
        Image(systemName: name)
            .resizable()
            .aspectRatio(contentMode: .fit)
            .padding(4)
            .frame(width: 40, height: 40)
    }
}

And then here's a view that uses it:

struct HelloView: View {
    var body: some View {
        CustomContainer {
            VStack {
                Text("hello")
                Text("khawar")
            }
        }
    }
}

import PlaygroundSupport
PlaygroundPage.current.setLiveView(HelloView())

Result:

output showing some content inside the custom container

Upvotes: 5

Related Questions