24

When I create a view in SwiftUI and render it in an Xcode preview, using PreviewLayout.sizeThatFits, the preview adjusts its size according to its content. When I import a UIKIt view using UIViewRepresentable, it appears with a full device-size frame.

Is there a way to make SwiftUI respect the intrinsicContentSize of UIView subclasses?

struct Label: UIViewRepresentable {

    func makeUIView(context: UIViewRepresentableContext<Label>) -> UILabel {
        return UILabel()
    }

    func updateUIView(_ uiView: UILabel, context: UIViewRepresentableContext<Label>) {
        uiView.text = "Some text"
    }
}

#if DEBUG
struct Label_Previews: PreviewProvider {
    static var previews: some View {
        Group {
            Label().previewLayout(.sizeThatFits)
        }
    }
}
#endif
knellr
  • 851
  • 8
  • 17

2 Answers2

32

Add the following to your updateUIView function:

uiView.setContentHuggingPriority(.defaultHigh, for: .vertical)
uiView.setContentHuggingPriority(.defaultHigh, for: .horizontal)
dwitt
  • 351
  • 2
  • 3
  • 3
    Thanks this is super helpful. Turns out that it also works when setting the contentHuggingPriorities in `makeUIView` after creating the view. It feels a bit cleaner to me because this needs to be configured only once, not every time the view is updated... – nils Dec 04 '20 at 16:47
  • I added this settings in `func makeUIView(context: Context) -> UIViewType`, it works well. Thanks for the suggestion! – Honghao Z May 24 '21 at 05:14
2

You can also limit the UIViewRepresentable size from the SwiftUI side.

For this you can use fixedSize:

struct Label_Previews: PreviewProvider {
    static var previews: some View {
        Label()
            .fixedSize()
            .previewLayout(.sizeThatFits)
    }
}

You can also fix the view size in one dimension only:

.fixedSize(horizontal: false, vertical: true)
pawello2222
  • 46,897
  • 22
  • 145
  • 209