SwiftUI:移除WebView点击操作,实现计时器自动启动及通知触发
解决方案:自动加载WebView并触发5秒后本地通知
Got it, let's tweak your code to remove the button requirement—so the WebView loads automatically, the timer starts right away, and the notification triggers after 5 seconds. Here's the revised code with key fixes to avoid common pitfalls like duplicate timers:
修改后的完整代码
import SwiftUI import WebKit import UserNotifications struct ContentView: View { @State private var showPermissionAlert = false var body: some View { // 移除按钮包装,直接显示WebView WebView() .edgesIgnoringSafeArea(.all) .onAppear { // 在视图出现时自动请求通知权限并安排通知 UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { (isGranted, error) in if isGranted { let content = UNMutableNotificationContent() content.title = "HEAD" content.body = "TEXT" // 创建5秒后触发的一次性通知 let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: false) let request = UNNotificationRequest(identifier: "autoNoti", content: content, trigger: trigger) UNUserNotificationCenter.current().add(request, withCompletionHandler: nil) } else { // 权限未授予时显示提示alert(切换到主队列保证UI更新安全) DispatchQueue.main.async { showPermissionAlert = true } } } } .alert(isPresented: $showPermissionAlert) { Alert(title: Text("Please Enable Notification Access In Settings Panel !!!")) } } } struct WebView: UIViewRepresentable { // 使用Coordinator管理计时器,避免重复创建导致的资源浪费 class Coordinator: NSObject { var timer: Timer? } func makeCoordinator() -> Coordinator { Coordinator() } func makeUIView(context: Context) -> WKWebView { let webView = WKWebView() webView.scrollView.isScrollEnabled = false return webView } func updateUIView(_ webView: WKWebView, context: Context) { let liveUrlString = "https://your-actual-url-here.com" // 替换为你的真实网页URL guard let url = URL(string: liveUrlString), webView.url != url else { // 如果WebView已经加载了目标URL,不再重复加载和创建计时器 return } let request = URLRequest(url: url) webView.load(request) // 先销毁旧计时器(如果存在),再创建新的 context.coordinator.timer?.invalidate() context.coordinator.timer = Timer.scheduledTimer(withTimeInterval: 5.0, repeats: true) { [weak webView] timer in guard let webView = webView else { timer.invalidate() return } webView.evaluateJavaScript("document.getElementById('ses').value") { (result, error) in if let error = error { print("JavaScript evaluation error: \(error.localizedDescription)") } else { print("Session value: \(result ?? "No value found")") } } } } // 视图销毁时清理计时器,防止内存泄漏 static func dismantleUIView(_ webView: WKWebView, coordinator: Coordinator) { coordinator.timer?.invalidate() } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } }
关键修改说明
- 移除按钮依赖:直接将WebView作为ContentView的主体内容,视图一出现就自动加载网页
- 自动触发通知逻辑:把通知权限请求和通知创建逻辑移到
onAppear修饰符中,无需用户手动点击触发 - 修复重复计时器问题:使用
Coordinator类持有计时器实例,每次加载新URL时先销毁旧计时器,避免多个计时器同时运行;同时在dismantleUIView中清理计时器,防止内存泄漏 - 线程安全处理:更新
showPermissionAlert时切换到主队列,确保UI操作在主线程执行 - 避免重复加载:添加
webView.url != url的判断,防止updateUIView被多次调用时重复加载同一个URL
内容的提问来源于stack exchange,提问作者Game Eagle
相关产品推荐
相关产品推荐

