SwiftUI `.popover` isn't working within UIHostingConfiguration cell displayed in a UITableViewController

I'm trying to use SwiftUI cells using the .contentConfiguration APIs. However, the SwiftUI view that I'd like to use also needs to be able to display a popover. I'm able to present an alert, but not able to present a popover.

The following code uses a SwiftUIView as the cell view that works to present an .alert but does not work to present a .popover. Note the .popover does work in both Previews and when presented within a UIHostingController.

import UIKit
import SwiftUI

class ViewController: UITableViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
    }
    
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        3
    }
    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell")!
        cell.contentConfiguration = UIHostingConfiguration { SwiftUIView(text: "Hello \(indexPath.row)") }

        return cell
    }
    
    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        present(UIHostingController(rootView: SwiftUIView(text: "full screen")), animated: true)
    }
}

struct SwiftUIView: View {
    @State var presentAlert: Bool = false
    @State var showPopover: Bool = false

    let text: String

    var body: some View {
        HStack {
            Text(text)
            Button("Present Alert") { presentAlert = true }
            Button("Present Popover") { showPopover = true }
        }.popover(isPresented: $showPopover) {
            Button("Hide Popover") {
                showPopover = false
            }
        }.alert(isPresented: $presentAlert) {
            Alert(title: Text("Alert"))
        }
    }
}

struct SwiftUIView_Previews: PreviewProvider {
    static var previews: some View {
        SwiftUIView(text: "Hello")
    }
}

Accepted Reply

UIHostingConfiguration does not support SwiftUI views or features that require a connection to the view controller hierarchy in UIKit. This includes things like navigation, toolbars, keyboard shortcuts, and views that use UIViewControllerRepresentable, as well as popover presentations. See the Use SwiftUI with UIKit video from WWDC22 to learn more. You need to use a UIHostingController in UIKit to be able to use these features in SwiftUI, so that SwiftUI has a connection to the view controller hierarchy in UIKit.

If you want to have a button (or other control) inside a cell using UIHostingConfiguration trigger a popover presentation, consider having the cell issue a callback to your table view controller (by passing a weak reference into the SwiftUI view), and then having that view controller manage the presentation of the popover. Having the view controller coordinate the presentation is often a better architecture in general for UIKit, rather than having a cell directly perform the presentation itself.

Replies

UIHostingConfiguration does not support SwiftUI views or features that require a connection to the view controller hierarchy in UIKit. This includes things like navigation, toolbars, keyboard shortcuts, and views that use UIViewControllerRepresentable, as well as popover presentations. See the Use SwiftUI with UIKit video from WWDC22 to learn more. You need to use a UIHostingController in UIKit to be able to use these features in SwiftUI, so that SwiftUI has a connection to the view controller hierarchy in UIKit.

If you want to have a button (or other control) inside a cell using UIHostingConfiguration trigger a popover presentation, consider having the cell issue a callback to your table view controller (by passing a weak reference into the SwiftUI view), and then having that view controller manage the presentation of the popover. Having the view controller coordinate the presentation is often a better architecture in general for UIKit, rather than having a cell directly perform the presentation itself.