'How to calculate dynamic height of UIViewControllerRepresentable

I am working on a SwiftUI project, I need to display MarkDownContent which is coming from api. (MarkDownContent can contain text, image url, list etc..)

I am using third party SDK Marky-Mark to render the Markdown String.

I am using UIViewControllerRepresentable to display the Markdown String.

As, I need to pass some height to the MarkDownView() to display the markdown contents.

My problem is, how can i calculate the height of UIViewControllerRepresentable markdown contents to display the data

My Code is

struct MarkDownView: UIViewControllerRepresentable {

@Binding var dynamicHeight: CGFloat

func makeUIViewController(context: Context) -> MarkDownViewController {
    let markDownVC = MarkDownViewController()
    return markDownVC
}

func updateUIViewController(_ uiViewController: MarkDownViewController, context: Context) {}


class MarkDownViewController: UIViewController {

var scrollView = UIScrollView()
var markDownView: UIView?

override func viewDidLoad() {
    super.viewDidLoad()
    scrollView.isScrollEnabled = false
    scrollView.backgroundColor = UIColor.yellow
    view.addSubview(scrollView)

    markDownView = getMarkDownView()
    scrollView.addSubview(markDownView!)
    
    
    let views: [String: Any] = [
        "view": view,
        "scrollView": scrollView,
        "markDownView": markDownView
        ]
    
    scrollView.translatesAutoresizingMaskIntoConstraints = false
    markDownView?.translatesAutoresizingMaskIntoConstraints = false

    var constraints: [NSLayoutConstraint] = []
    
    constraints += NSLayoutConstraint.constraints(withVisualFormat: "V:|[scrollView]|", options: [], metrics: [:], views: views)
    constraints += NSLayoutConstraint.constraints(withVisualFormat: "H:|[scrollView]|", options: [], metrics: [:], views: views)
    constraints += NSLayoutConstraint.constraints(withVisualFormat: "H:|[markDownView(==scrollView)]|", options: [], metrics: [:], views: views)
    constraints += NSLayoutConstraint.constraints(withVisualFormat: "V:|[markDownView]|", options: [], metrics: [:], views: views)
    
    view.addConstraints(constraints)
    view.layoutIfNeeded()
  }
}

private extension MarkDownViewController {

func getMarkDownView() -> UIView {

    // Parsing to MarkDownItem's
    let markDownString = getMarkDownString()

    let markyMark = MarkyMark(build: {
        // Choose flavor (set of rules)
        $0.setFlavor(ContentfulFlavor())

        //Example: Add single custom rules
        //$0.addRule(CustomHeaderRule())
    })

    let markDownItems = markyMark.parseMarkDown(markDownString)
    
    // Configure styling, see README for more styling options or Implement your own Styling object instead of DefaultStyling.
    let styling = DefaultStyling()
    
    
    styling.listStyling.bulletColor = UIColor.red
    
    styling.imageStyling.contentInsets = UIEdgeInsets(top: 10, left: 20, bottom: 10, right: 20)
    
    styling.paragraphStyling.baseFont = UIFont.italicSystemFont(ofSize: 30)


    styling.headingStyling.contentInsetsForLevels = [
        UIEdgeInsets(top: 16, left: 6, bottom: 15, right: 10), // H1
        UIEdgeInsets(top: 5, left: 0, bottom: 5, right: 10) // H2, ...
    ]

    styling.headingStyling.textColorsForLevels = [
        .red,  // H1
        .black, // H2
        .gray // H3, ...
    ]

    // Only uppercase H1 headers
    styling.headingStyling.capitalizationForLevels = [
        .uppercased, // H1
        nil //H2, ...
    ]
    
    styling.linkStyling.textColor = UIColor.green

    let configuration = MarkdownToViewConverterConfiguration(styling: styling)
    let converter = MarkDownConverter(configuration: configuration)

    // Converter hook, only meant for very specific (otherwise impossible) usecases. The hook is triggered every time a MarkdownItem is converted to a view.
    // In this example the headers are rotated, which is normally not supported in MarkyMark styling.
    converter.didConvertElement = {
        markdownItem, view in
    }
    
    return converter.convert(markDownItems)
}

func getMarkDownString() -> String {
    var markdownString: String = ""
    if let filepath = Bundle.main.path(forResource: "hello", ofType: "md") {
        markdownString = try! String(contentsOfFile: filepath)
    }

    return markdownString
}

SwiftUI Code

struct ContentView: View {

@State private var height: CGFloat = .zero

var body: some View {        
    ScrollView {
        VStack {
            
            MarkDownView(dynamicHeight: $height)
              //  .frame(height:1500)
        }
    }
    
        .ignoresSafeArea()
}

}

In MarkDownViewController class, in UIScrollView I am adding Markdown view to show it as scrollable content

For testing purpose i have passed height of Markdown View hardcoded, but it should be dynamic as the content of MarkDown View will be different.

I need to pass height of MarkDownViewController from UIViewRepresentable to SwiftUI View using @Bindings

How can i calculate the height of UIViewRepresentable ? Please help me with this



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source