如何让Home Widget直接跳转目标ViewController,无需启动主ViewController?
问题描述
点击Home Widget时,当前逻辑会先启动父主ViewController,再打开所需的黄色编辑器ViewController。需要实现点击Widget后直接跳转至目标ViewController,无需先启动主ViewController。
现有代码片段
Home Widget代码
struct sticky_note_widgetEntryView : View { var entry: Provider.Entry private let widgetURLTemplate = "xxx://widget?objectIDAsString=" @ViewBuilder func contentView(stickyNote: StickyNote, showTitleBar: Bool, showImageAttachments: Bool, widgetWidth: Double) -> some View { let url = URL(string: widgetURLTemplate + objectIDAsString) let contentView = VStack(alignment: .leading, spacing: 0) { } .widgetURL(url) contentView } }
SceneDelegate代码
class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? static var incomingURL: URL? = nil func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { guard let windowScene = (scene as? UIWindowScene) else { return } // 优先处理Widget启动URL if let url = connectionOptions.urlContexts.first?.url { if handleWidgetURLAndSetRootVC(url, windowScene: windowScene) { return } } // 无Widget URL时,正常初始化主VC let mainVC = MainViewController() let navigationController = UINavigationController(rootViewController: mainVC) window = UIWindow(windowScene: windowScene) window?.rootViewController = navigationController window?.makeKeyAndVisible() } // 处理后台唤起的URL func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) { if let url = URLContexts.first?.url { _ = handleIncomingURL(url) } } // 处理Widget URL并直接设置根VC(冷启动场景) private func handleWidgetURLAndSetRootVC(_ url: URL, windowScene: UIWindowScene) -> Bool { guard let scheme = url.scheme, scheme == "xxx", let page = url.host, page == "widget" else { return false } var parameters: [String: String] = [:] URLComponents(url: url, resolvingAgainstBaseURL: false)?.queryItems?.forEach { parameters[$0.name] = $0.value } guard let objectIDAsString = parameters["objectIDAsString"], let objectID = NSManagedObjectID.from(objectIDAsString) else { return false } // 替换为你实际的黄色编辑器VC初始化代码 let yellowEditorVC = YellowEditorViewController(objectID: objectID) let navigationController = UINavigationController(rootViewController: yellowEditorVC) window = UIWindow(windowScene: windowScene) window?.rootViewController = navigationController window?.makeKeyAndVisible() return true } // 处理URL(后台唤起场景) static func handleIncomingURL(_ url: URL) -> Bool { guard let scheme = url.scheme, scheme == "xxx", let page = url.host else { return false } var parameters: [String: String] = [:] URLComponents(url: url, resolvingAgainstBaseURL: false)?.queryItems?.forEach { parameters[$0.name] = $0.value } guard let window = UIWindow.key else { return false } let rootViewController = window.rootViewController switch page { case "widget": guard let objectIDAsString = parameters["objectIDAsString"], let objectID = NSManagedObjectID.from(objectIDAsString) else { return true } // 替换为你实际的黄色编辑器VC初始化代码 let yellowEditorVC = YellowEditorViewController(objectID: objectID) if let navController = rootViewController as? UINavigationController { // 直接替换导航栈,跳过主VC navController.setViewControllers([yellowEditorVC], animated: true) } else { // 若当前根不是导航控制器,直接设置为根 let navController = UINavigationController(rootViewController: yellowEditorVC) window.rootViewController = navController } default: precondition(false) } return true } }
父主ViewController代码
class MainViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() handleIncomingURLIfPossible() } private func handleIncomingURLIfPossible() -> Bool { if let incomingURL = SceneDelegate.incomingURL { SceneDelegate.incomingURL = nil SceneDelegate.handleIncomingURL(incomingURL) return true } else { return false } } }
核心修改说明
冷启动直接加载目标VC:
在scene(_:willConnectTo:)方法中优先检查Widget启动URL,若存在则直接初始化黄色编辑器VC并设为窗口根控制器,跳过主VC的初始化流程。后台唤起直接跳转目标VC:
修改handleIncomingURL方法,处理Widget URL时直接替换导航栈为目标VC,避免主VC被展示。移除主VC依赖:
所有Widget相关的URL处理逻辑移至SceneDelegate独立完成,不再依赖主VC中转。
内容的提问来源于stack exchange,提问作者Cheok Yan Cheng
相关产品推荐
相关产品推荐

