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

如何让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
        }
    }
}

核心修改说明

  1. 冷启动直接加载目标VC:
    在scene(_:willConnectTo:)方法中优先检查Widget启动URL,若存在则直接初始化黄色编辑器VC并设为窗口根控制器,跳过主VC的初始化流程。

  2. 后台唤起直接跳转目标VC:
    修改handleIncomingURL方法,处理Widget URL时直接替换导航栈为目标VC,避免主VC被展示。

  3. 移除主VC依赖:
    所有Widget相关的URL处理逻辑移至SceneDelegate独立完成,不再依赖主VC中转。

内容的提问来源于stack exchange,提问作者Cheok Yan Cheng

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 08:13:18