Skip to content

Instantly share code, notes, and snippets.

@macguru
Last active November 9, 2022 17:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save macguru/1163a27af6db71ae905bab0f58295474 to your computer and use it in GitHub Desktop.
Save macguru/1163a27af6db71ae905bab0f58295474 to your computer and use it in GitHub Desktop.
Adapter view to use a (wrapping) SwiftUI view with auto layout, where a certain width is pre-defined
import SwiftUI
public final class SwiftUIView<Content: View>: UIView {
private let hostingController: UIHostingController<Content>
public init(rootView: Content) {
hostingController = UIHostingController(rootView: rootView)
super.init(frame: .zero)
let hostedView = hostingController.view
addSubview(hostedView)
hostedView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
hostedView.leadingAnchor.constraint(equalTo: leadingAnchor),
hostedView.trailingAnchor.constraint(equalTo: trailingAnchor),
hostedView.topAnchor.constraint(equalTo: topAnchor),
hostedView.bottomAnchor.constraint(equalTo: bottomAnchor)
])
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
public override var frame: NSRect {
didSet {
if frame.width != oldValue.width {
let constrainedSize = CGSize(width: frame.width, height: .infinity)
let fittingSize = hostingController.sizeThatFits(in: constrainedSize)
intrinsicContentHeight = fittingSize.height
}
}
}
private var intrinsicContentHeight: CGFloat = UIView.noIntrinsicMetric {
didSet {
if intrinsicContentHeight != oldValue {
invalidateIntrinsicContentSize()
}
}
}
public override var intrinsicContentSize: NSSize {
CGSize(width: UIView.noIntrinsicMetric, height: intrinsicContentHeight)
}
}
@macguru
Copy link
Author

macguru commented Nov 9, 2022

UIKit classes (UIView, UIHostingController) can be replaced by AppKit classes (NSView, NSHostingController), code works there as well.

Instantly pre-computing the intrinsicContentSize seems to perform better on dynamic changes of the height. Whereas observing the view's layouted size (as Tunous' SwiftUIView.swift) or using above approach with a layout constraint show small delays in updating themselves.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment