0

So I have the following in my project.

  1. ContentView ~ contains 3 vstacks.
  2. CustomView ~ a custom view with a containerView with fixed size of 300x300 that should always be centered in ContentView
  3. CustomViewRepresentable ~ a UIViewRepresentable in order to insert CustomView into ContentView.

The code for each is as follows:

ContentView

import SwiftUI
import UIKit

struct ContentView: View {
    
    var body: some View {
        VStack(alignment: .center, spacing: 0) {
            VStack {
                Color.blue
                    .frame(height: 50)
            }
            VStack {
                HStack {
                    Color.green
                        .frame(height: 100)
                    Text("Text")
                    Color.green
                        .frame(height: 100)
                }
            }
            VStack { // content view
                GeometryReader { geometry in
                    VStack {
                        CustomViewRepresentable()
                            .frame(width: geometry.size.width, height: geometry.size.height)
                            .background(.gray)
                            .border(.red, width: 1)
                    }
                    .frame(width: geometry.size.width, height: geometry.size.height)
                }
            }
        }
    }
}

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

CustomView

import UIKit

class CustomView: UIView {
    private let containerView = UIView()
    override func layoutSubviews() {
        containerView.center = self.center
    }

    func addContainerView() {
        containerView.frame = CGRect(origin: .zero, size: CGSize(width: 300, height: 300))
        addSubview(containerView)
        containerView.center = self.center
    }
}

CustomViewRepresentable

import UIKit
import SwiftUI

struct CustomViewRepresentable: UIViewRepresentable {
    typealias UIViewType = CustomView
    
    func makeUIView(context: Context) -> CustomView {
        let customView = CustomView(frame: CGRect(x: 0, y: 0, width: 300, height: 300))
        customView.addContainerView()
        return customView
    }

    func updateUIView(_ uiView: CustomView, context: Context) {
        
    }
}

The issue that I'm facing is that the containerView inside CustomView does not display unless I initialise CustomView with a frame inside the representable.

func makeUIView(context: Context) -> CustomView {
        let customView = CustomView(frame: CGRect(x: 0, y: 0, width: 300, height: 300))

I don't understand why this is needed because I'd like the CustomView to take the full width and height of the VStack that it is embedded into. Therefore I figured that just doing

CustomViewRepresentable()
   .frame(width: geometry.size.width, height: geometry.size.height)

inside the VStack should just work, but apparently it does not. So what is the best way for the CustomViewRepresentable to fill its parent while keeping the containerView always centered within it?

5
  • "unless I initialise CustomView with a frame inside the representable" How else would you initialise it? let customView = CustomView() works just as well for me. Commented Aug 28, 2023 at 4:56
  • it does not work for me in the sense that if I dont set the frame, the containerView does not show at all. Commented Aug 28, 2023 at 5:02
  • What do you mean by " I dont set the frame"? Please show a minimal reproducible example. Commented Aug 28, 2023 at 5:04
  • inside makeUIView, I need to do let customView = CustomView(frame: CGRect(x: 0, y: 0, width: 300, height: 300)) instead of just let customView = CustomView(). Only then does the containerView inside the CustomView show. Commented Aug 28, 2023 at 5:06
  • Well I cannot reproduce. The container view still appears. Commented Aug 28, 2023 at 5:09

1 Answer 1

0

No need to provide the CustomView frame in func makeUIView(context: Context) -> CustomView function. After replacing let customView = CustomView(frame: CGRect(x: 0, y: 0, width: 300, height: 300)) code with let customView = CustomView() working at my end. Please check with the code below.

ContenView

import SwiftUI
import UIKit

struct ContentView: View {
    
    var body: some View {
        VStack(alignment: .center, spacing: 0) {
            VStack {
                Color.blue
                    .frame(height: 50)
            }
            VStack {
                HStack {
                    Color.green
                        .frame(height: 100)
                    Text("Text")
                    Color.green
                        .frame(height: 100)
                }
            }
            VStack { // content view
                GeometryReader { geometry in
                    VStack {
                        CustomViewRepresentable()
                            .background(.gray)
                            .border(.red, width: 1)
                    }
                    .frame(width: geometry.size.width, height: geometry.size.height)
                }
            }
        }
    }
}

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

CustomView

import UIKit

class CustomView: UIView {
    private let containerView = UIView()
    override func layoutSubviews() {
        containerView.center = self.center
    }

    func addContainerView() {
        containerView.frame = CGRect(origin: .zero, size: CGSize(width: 300, height: 300))
        addSubview(containerView)
        containerView.center = self.center
    }
}

CustomViewRepresentable

import UIKit
import SwiftUI

struct CustomViewRepresentable: UIViewRepresentable {
    typealias UIViewType = CustomView
    
    func makeUIView(context: Context) -> CustomView {
        let customView = CustomView(frame: CGRect(x: 0, y: 0, width: 300, height: 300))
        customView.addContainerView()
        return customView
    }

    func updateUIView(_ uiView: CustomView, context: Context) {
        
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.