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

SwiftUI应用如何从WeatherKit获取实时天气警报(降雨、龙卷风等)

实现WeatherKit实时天气警报推送的方案

WeatherKit本身没有提供Webhook式的主动推送能力,要实现你要的「龙卷风警报触发→推送通知给应用」的流程,得结合轮询WeatherKit警报API和**苹果推送通知服务(APNs)**搭建逻辑,具体步骤如下:

1. 选择轮询载体:后端服务或iOS后台任务

后端服务方案(推荐,时效性更高)

如果有自己的后端服务器,用它定期拉取WeatherKit警报数据是最优解:

  • 定时调用WeatherKit的天气警报API,传入目标地区ID和语言参数;
  • 每次拉取后,将返回的警报与本地存储的历史警报对比(用警报的identifier或effectiveTime判断是否为新增);
  • 一旦发现新增的龙卷风类警报,构造APNs推送payload,调用APNs接口给应用发通知。

iOS后台任务方案(无后端时备选)

如果没有后端,可借助iOS的BackgroundTasks框架实现本地轮询,但需注意系统对后台任务的刷新间隔有管控,无法做到严格实时:

  • 注册后台刷新任务,定期唤醒应用拉取WeatherKit警报;
  • 对比出新增警报后,直接触发本地通知。

2. 调用WeatherKit警报API的Swift示例代码

不管是后端还是iOS端,调用API都需要JWT鉴权令牌(在Apple Developer后台生成对应密钥后生成),示例代码如下:

import Foundation

// 定义解码用的模型
struct WeatherAlertResponse: Codable {
    let alerts: [WeatherAlert]
}

struct WeatherAlert: Codable {
    let identifier: String
    let event: String
    let effectiveTime: Date
    let severity: String
    let description: String
}

func fetchWeatherAlerts(locationId: String, language: String, jwtToken: String) async throws -> [WeatherAlert] {
    guard let url = URL(string: "https://weatherkit.apple.com/api/v1/weather/\(language)/\(locationId)") else {
        throw NSError(domain: "InvalidURL", code: 0)
    }
    
    var request = URLRequest(url: url)
    request.setValue("Bearer \(jwtToken)", forHTTPHeaderField: "Authorization")
    
    let (data, response) = try await URLSession.shared.data(for: request)
    guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else {
        throw NSError(domain: "APIError", code: (response as? HTTPURLResponse)?.statusCode ?? 500)
    }
    
    let decoder = JSONDecoder()
    decoder.dateDecodingStrategy = .iso8601
    return try decoder.decode(WeatherAlertResponse.self, from: data).alerts
}

3. 检测新增警报并触发推送

后端触发APNs推送

当后端检测到新增龙卷风警报时,构造APNs payload示例:

{
    "aps": {
        "alert": {
            "title": "紧急天气警报",
            "body": "\(alert.event):\(alert.description)"
        },
        "sound": "default",
        "content-available": 1
    },
    "alertDetails": {
        "id": "\(alert.identifier)",
        "severity": "\(alert.severity)"
    }
}

随后用APNs的P8密钥鉴权,调用APNs推送接口发送通知。

iOS本地触发通知(无后端时)

如果用iOS后台任务,检测到新增警报后直接发本地通知:

func sendLocalAlert(alert: WeatherAlert) {
    let content = UNMutableNotificationContent()
    content.title = "紧急天气警报"
    content.body = "\(alert.event):\(alert.description)"
    content.sound = .default
    
    let request = UNNotificationRequest(identifier: alert.identifier, content: content, trigger: nil)
    UNUserNotificationCenter.current().add(request)
}

4. SwiftUI应用处理通知

确保应用已配置远程/本地通知权限,在App结构体中注册通知回调:

import SwiftUI
import UserNotifications

@main
struct WeatherAlertApp: App {
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
    
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

class AppDelegate: NSObject, UIApplicationDelegate, UNUserNotificationCenterDelegate {
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        UNUserNotificationCenter.current().delegate = self
        
        // 请求通知权限
        UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { granted, error in
            if granted {
                DispatchQueue.main.async {
                    application.registerForRemoteNotifications()
                }
            }
        }
        return true
    }
    
    // 前台收到通知时展示
    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        completionHandler([.alert, .sound])
    }
    
    // 用户点击通知后的处理
    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
        let userInfo = response.notification.request.content.userInfo
        // 解析自定义数据,跳转到详情页
        if let alertDetails = userInfo["alertDetails"] as? [String: String] {
            // 可通过ObservableObject或NotificationCenter传递数据到视图
        }
        completionHandler()
    }
}

关键注意事项

  • JWT令牌和APNs的P8密钥要安全存储,绝对不能硬编码在iOS客户端代码中;
  • 后端轮询间隔可设置为5-10分钟,平衡时效性和API调用次数;
  • iOS后台任务的刷新间隔由系统决定,可能因应用活跃度、设备电量等因素延长,适合非极端实时的场景;
  • 要处理API调用失败的情况,比如网络错误、令牌过期,添加重试逻辑保证稳定性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 13:33:20