You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在SwiftUI中处理UIViewControllerRepresentable封装的TableViewController导航?

在SwiftUI中复用UIKit联系人列表时实现页面跳转的解决方案

方法一:使用SwiftUI原生导航机制(推荐)

这种方式更贴合SwiftUI的设计范式,将跳转逻辑交给SwiftUI统一处理,避免混合UIKit导航带来的兼容性问题:

  1. 修改ContactView,添加绑定属性跟踪选中的联系人:
struct ContactView: UIViewControllerRepresentable {
    let viewModel: ContactsViewModel
    @Binding var selectedContact: Contact? // 替换为你的联系人模型类型

    func makeUIViewController(context: Context) -> ContactsTableViewController {
        let vc = ContactsTableViewController(viewModel: viewModel)
        vc.tableView.delegate = context.coordinator
        return vc
    }

    func updateUIViewController(_ uiViewController: ContactsTableViewController, context: Context) {
    }
}
  1. 更新Coordinator,选中联系人时修改绑定状态:
extension ContactView {
    class Coordinator: NSObject, UITableViewDelegate {
        var parent: ContactView

        init(_ parent: ContactView) {
            self.parent = parent
        }

        func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
            let contact = parent.viewModel.contacts[indexPath.row]
            parent.selectedContact = contact
            tableView.deselectRow(at: indexPath, animated: true)
        }
    }

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
}
  1. 在SwiftUI主视图中用NavigationStack处理跳转:
    如果详情页是UIKit的DetailViewController,先将其包装为UIViewControllerRepresentable:
struct DetailViewRepresentable: UIViewControllerRepresentable {
    let contact: Contact

    func makeUIViewController(context: Context) -> DetailViewController {
        let dependencies = DetailsViewModel.Dependencies(
            contacts: parent.viewModel.contacts,
            contactMethod: contact.contactMethod
        )
        let viewModel = DetailsViewModel(dependencies: dependencies)
        return viewModel.detailViewControllerFactory(viewModel.contacts, contact.contactMethod)
    }

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

然后在主视图中配置导航:

struct MainContentView: View {
    @State private var selectedContact: Contact?
    let viewModel: ContactsViewModel

    var body: some View {
        NavigationStack {
            ContactView(viewModel: viewModel, selectedContact: $selectedContact)
                .navigationDestination(item: $selectedContact) { contact in
                    DetailViewRepresentable(contact: contact)
                }
        }
    }
}

方法二:直接使用UIKit导航控制器推送

如果需要保留UIKit的pushViewController逻辑,可以通过获取宿主视图控制器的导航引用实现:

  1. 给Coordinator添加ContactsTableViewController的引用:
extension ContactView {
    class Coordinator: NSObject, UITableViewDelegate {
        var parent: ContactView
        weak var hostVC: ContactsTableViewController? // 宿主视图控制器引用

        init(_ parent: ContactView) {
            self.parent = parent
        }

        func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
            let contact = parent.viewModel.contacts[indexPath.row]
            
            // 创建详情视图控制器
            let dependencies = DetailsViewModel.Dependencies(
                contacts: parent.viewModel.contacts,
                contactMethod: contact.contactMethod
            )
            let viewModel = DetailsViewModel(dependencies: dependencies)
            let detailsViewController = viewModel.detailViewControllerFactory(viewModel.contacts, contact.contactMethod)
            
            // 获取导航控制器并推送
            if let navController = hostVC?.navigationController {
                navController.pushViewController(detailsViewController, animated: true)
            }
            tableView.deselectRow(at: indexPath, animated: true)
        }
    }

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
}
  1. 在makeUIViewController中给Coordinator赋值宿主VC:
func makeUIViewController(context: Context) -> ContactsTableViewController {
    let vc = ContactsTableViewController(viewModel: viewModel)
    vc.tableView.delegate = context.coordinator
    context.coordinator.hostVC = vc // 传递宿主VC引用
    return vc
}

注意:此方法要求ContactView必须嵌入在SwiftUI的NavigationStack(iOS 15及以下用NavigationView)中,否则navigationController会返回nil。

内容的提问来源于stack exchange,提问作者onthemoon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 15:50:15