Conforming a SwiftUI View to CustomPlaygroundDisplayConvertible

I was playing around with SwiftUI in a playground and wanted to create a way for SwiftUI View's to show inline like UIView's. While I know that you can show views using PlaygroundPage.current.setLiveView(_:), I want to be able to show it inline and use the quick look feature in playgrounds. To do this, I tried to create a type to wrap SwiftUI views that itself conforms to CustomPlaygroundDisplayConvertible. And for the sake of convenience, I decided to write an extension on View to wrap said view in the type. I figured that since returning a UIView in playgroundDescription works, all I would have to do is wrap my view in a UIHostingController, and as such, here's what I did:

struct PlaygroundView<T: View>: View, CustomPlaygroundDisplayConvertible {
  var body: T
   
  var playgroundDescription: Any {
    return UIHostingController(rootView: self)
  }
}

extension View {
  func playgroundView() -> PlaygroundView<Self> {
    return PlaygroundView(body: self)
  }
}

I tried to use the code as such:

struct Square: View {
  var body: some View {
    Rectangle()
      .fill(Color.red)
      .frame(width: 100, height: 100)
  }
}

Square().playgroundView()

Unfortunately, this did not work for some reason. I also tried returning UIHostingController(rootView: body).view! from playgroundDescription to no avail.

I am 99.9% positive that there is no way around conforming to CustomPlaygroundDisplayConvertible to enable these features. Even so, I am not sure why it doesn't work.

Is there any way to accomplish this and make use of Swift Playground's quick look and inline representation features for SwiftUI views?

1 Like

There’s a note in the Xcode 11.4 release notes that seems relevant:

Known Issues

  • SwiftUI views aren’t rendered by Quick Look previews or inline result views. (59908350)

Granted, the note is about playgrounds in Xcode and not necessarily Swift Playgrounds, but it seems like a similar situation.

1 Like