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

SwiftUI按钮点击展示Objective-C UIViewController的实现方案

在Objective-C项目中从SwiftUI以FormSheet样式展示现有UIViewController的解决方案

问题背景

刚接触SwiftUI,在现有Objective-C项目中引入SwiftUI模块,通过UIHostingController在SwiftViewControllerUsedToPresentSwiftUI中初始化SwiftUI视图(struct ContentView: View),代码如下,这部分运行正常:

let hostingController = UIHostingController.init(rootView: ContentView())

需求是在SwiftUI视图的按钮点击时,调用项目中带关联xib的现有MyExistingUIViewController,理想实现代码如下:

let myExistingUIViewController = MyExistingUIViewController(nibName: "MyExistingUIViewController", bundle: nil)
myExistingUIViewController.modalPresentationStyle = .formSheet
present(myExistingUIViewController, animated: true, completion: nil)

尝试直接通过宿主VC调用时,出现以下错误:

[Presentation] Attempt to present <MyExistingUIViewController: 0x7f7a67827c00> on <SwiftViewControllerUsedToPresentSwiftUI: 0x7f7a64720da0> (from <SwiftViewControllerUsedToPresentSwiftUI: 0x7f7a64720da0>) whose view is not in the window hierarchy.

后续按照建议用UIViewControllerRepresentable包装现有VC:

import Foundation
import SwiftUI

struct MyExistingUIViewControllerWrapper: UIViewControllerRepresentable{
    func makeUIViewController(context: Context) -> MyExistingUIViewController {
        let vc = MyExistingUIViewController(nibName: "MyExistingView", bundle: nil)
        return vc
    }

    func updateUIViewController(_ uiViewController: MyExistingUIViewController, context: Context) {
        // 相关代码
    }
}

通过SwiftUI的.sheet调用时:

.sheet(isPresented: $showingWrapperView){
    MyExistingUIViewControllerWrapper()
}

但无法以formSheet样式展示,而现有xib对应的VC本身是formSheet样式。

解决方案

页面流转路径为:Objective-C View Controller → SwiftUI → Objective-C Form Sheet,通过从初始的FirstObjCViewController向SwiftUI视图传递两个闭包Handler,实现需求:

  • 一个Handler用于关闭当前SwiftUI视图
  • 另一个Handler用于关闭SwiftUI视图,并从FirstObjCViewController打开目标FormSheet类型的MyExistingUIViewController

代码实现

  1. Objective-C侧创建SwiftUI视图的代码:
UIViewController *newSwiftUIView = [NewSwiftUIView makeNewSwiftUIView WithSomeFirstArg:someFirstArg 
                                                                           closeHandler:^{
                                                                               [[self presentedViewController] dismissViewControllerAnimated:YES completion:nil];
                                                                           } 
                                 closeAndOpenMyExistingUIViewControllerHandler:^{
                                                                               [[self presentedViewController] dismissViewControllerAnimated:YES completion:nil];
                                                                               [self OpenMyExistingUIViewController]; // 此方法在FirstObjCViewController中定义,负责以FormSheet样式打开目标VC
                                                                           }];
  1. Swift侧接收Handler的方法定义:
@objc static func makeNewSwiftUIView(someFirstArg: NSArray, 
                                     closeHandler: @escaping (() -> Void), 
                                     closeAndOpenMyExistingUIViewControllerHandler: @escaping (() -> Void)) -> UIViewController

这种实现方式运行流畅、代码简洁,可直接复用现有Objective-C侧的VC展示逻辑,保证FormSheet样式正常生效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 21:00:51