SwiftUI

UIKit

Wrapping UIKit Views

UIKit or custom UIViews can be presented using the UIViewRepresentable protocol.

struct ContentView: View {
    @State var isLoading = false

    var body: some View {
        Activity(style: .large, isAnimating: $isLoading)
    }
}

struct Activity : UIViewRepresentable {
    let style: UIActivityIndicatorView.Style
    @Binding var isAnimating: Bool

    init(style: UIActivityIndicatorView.Style = .medium, isAnimating: Binding<Bool>) {
        self.style = style
        self._isAnimating = isAnimating
    }

    func makeUIView(context: Context) -> UIActivityIndicatorView {
        let indicator = UIActivityIndicatorView(style: style)
        indicator.hidesWhenStopped = true
        return indicator
    }

    func updateUIView(_ uiView: UIActivityIndicatorView, context: Context) {
        if isAnimating {
            uiView.startAnimating()
        } else {
            uiView.stopAnimating()
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

State

Preferences

Using preferences you can push state values from child to parent views.

The example below creates a circle relative to the width of the label:

struct ContentView: View {
    var body: some View {
        Label(message: "Swift")
    }
}

struct Label: View {
    @State var message: String
    @State
    private var size: CGSize?

    var body: some View {
        Circle()
            .fill(Color.blue)
            .frame(width: self.size?.width, height: self.size?.width)
            .overlay(
                Text(message)
                .font(.title)
                .foregroundColor(.white)
                .padding(5)
                .overlay(GeometryReader { geometry in
                    Color.clear
                        .preference(
                            key: LabelSizePreference.self,
                            value: geometry.size)
                })
            )
            .onPreferenceChange(LabelSizePreference.self, perform: { size in
                self.size = size
            })
    }
}

struct LabelSizePreference: PreferenceKey {
    static var defaultValue: CGSize?

    static func reduce(value: inout CGSize?, nextValue: () -> CGSize?) {
        value = value ?? nextValue()
    }
}

Last updated

Was this helpful?