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

watchOS中SwiftUI实现点击通知跳转指定视图的方法

在SwiftUI中处理通知点击并导航到指定页面

嘿,我刚好在项目里处理过类似的需求,给你详细说下SwiftUI里实现通知点击跳转指定页面的完整流程,分几步来:

1. 给通知附加目标页面的标识信息

首先,在创建推送通知的时候,一定要在userInfo字典里添加自定义字段,用来标记要跳转的目标页面,还可以带上页面需要的参数(比如商品ID)。示例代码:

import UserNotifications

func sendSampleNotification() {
    let content = UNMutableNotificationContent()
    content.title = "新消息提醒"
    content.body = "点击查看详情"
    // 自定义字段:标记目标页面,以及传递参数
    content.userInfo = [
        "targetView": "ProductDetail",
        "productId": "1001"
    ]
    
    let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: false)
    let request = UNNotificationRequest(identifier: "sampleNotification", content: content, trigger: trigger)
    
    UNUserNotificationCenter.current().add(request)
}

2. 设置通知代理并处理点击事件

接下来要实现UNUserNotificationCenterDelegate的didReceive方法,这个方法会在用户点击通知时触发。我们需要在这里解析userInfo里的信息,然后通知SwiftUI的导航逻辑。

第一步:创建导航状态管理器

因为SwiftUI是声明式UI,我们需要一个可观察的对象来管理导航状态,这样代理方法里的变化能实时反映到UI上:

import SwiftUI

class NavigationManager: ObservableObject {
    // 存储目标页面标识
    @Published var targetView: String? = nil
    // 存储页面所需参数
    @Published var productId: String? = nil
    // 如果用NavigationStack的path,也可以用这个来管理导航栈
    @Published var navigationPath = NavigationPath()
}

第二步:设置通知代理并实现didReceive方法

在你的App入口或者SceneDelegate里设置代理,比如在App结构体的初始化方法里:

@main
struct MyShopApp: App, UNUserNotificationCenterDelegate {
    let navigationManager = NavigationManager()
    
    init() {
        // 请求通知权限
        UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { granted, error in
            if granted {
                print("通知权限已授权")
            }
        }
        // 设置代理
        UNUserNotificationCenter.current().delegate = self
    }
    
    // 实现通知点击代理方法
    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
        let userInfo = response.notification.request.content.userInfo
        
        // 解析目标页面和参数
        if let target = userInfo["targetView"] as? String {
            navigationManager.targetView = target
            navigationManager.productId = userInfo["productId"] as? String
            
            // 如果用NavigationPath的方式,直接把目标页面标识加入栈
            navigationManager.navigationPath.append(target)
        }
        
        completionHandler()
    }
    
    var body: some Scene {
        WindowGroup {
            NavigationStack(path: $navigationManager.navigationPath) {
                HomeView()
                    .environmentObject(navigationManager)
            }
        }
    }
}

3. 在SwiftUI视图中实现导航跳转

现在把NavigationManager通过环境对象传递给视图,然后根据状态自动导航:

方式一:使用NavigationStack(iOS 16+)

struct HomeView: View {
    @EnvironmentObject var navManager: NavigationManager
    
    var body: some View {
        VStack(spacing: 20) {
            Text("首页内容")
                .font(.title)
        }
        // 定义导航目标
        .navigationDestination(for: String.self) { target in
            switch target {
            case "ProductDetail":
                ProductDetailView(productId: navManager.productId ?? "")
            case "Settings":
                SettingsView()
            default:
                EmptyView()
            }
        }
    }
}

// 示例详情页
struct ProductDetailView: View {
    let productId: String
    
    var body: some View {
        Text("商品ID:\(productId)")
            .navigationTitle("商品详情")
    }
}

方式二:使用NavigationView(iOS 15及以下)

如果需要兼容旧版本,可以用NavigationLink结合isActive绑定:

// 先修改NavigationManager,添加isActive状态
class NavigationManager: ObservableObject {
    @Published var showProductDetail = false
    @Published var productId: String? = nil
}

// 然后在HomeView里添加隐藏的NavigationLink
struct HomeView: View {
    @EnvironmentObject var navManager: NavigationManager
    
    var body: some View {
        NavigationView {
            VStack(spacing: 20) {
                Text("首页内容")
                    .font(.title)
                
                // 隐藏的NavigationLink,通过isActive控制跳转
                NavigationLink(
                    destination: ProductDetailView(productId: navManager.productId ?? ""),
                    isActive: $navManager.showProductDetail
                ) {
                    EmptyView()
                }
                .hidden()
            }
        }
    }
}

// 代理方法里修改状态
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
    let userInfo = response.notification.request.content.userInfo
    
    if userInfo["targetView"] as? String == "ProductDetail" {
        navManager.productId = userInfo["productId"] as? String
        navManager.showProductDetail = true
    }
    
    completionHandler()
}

几个注意点

  • 确保已经成功申请了通知权限,否则通知无法正常接收。
  • 无论是前台还是后台点击通知,didReceive方法都会触发,逻辑一致。
  • 尽量避免用单例管理导航状态,用环境对象(EnvironmentObject)或者ObservedObject更符合SwiftUI的状态管理规范。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 07:25:23