【发布时间】:2021-02-08 22:00:21
【问题描述】:
我正在尝试获取通知操作以打开自定义视图。我的通知基本上是新闻,我希望用户在点击“阅读通知”操作时转到显示简单文本的页面(出于此问题的目的)。 我已经尝试了大量的教程,但它们都使用了一些现有的视图,比如“imagePicker”,默认情况下已经启用了大量的东西,我不知道我需要添加到我的自定义视图中以使其工作的所有东西.像 UIViewControllerRepresentable、协调器或其他我可能需要的东西。
这是我处理通知的主要 swift 文件。(通知工作正常) 文件末尾是扩展名 AppDelegate: UNUserNotificationCenterDelegate {},取自我正在遵循的教程,它创建了一个 NewsItem,我也将在此处包含它。但由于我使用的是 SwiftUI 而不是 UIKit,所以我无法按照我设法找到的任何教程来让它按照我想要的方式工作。
我已包含完整的应用程序委托扩展和 newsItem 只是为了使此处的代码可编译,但我将需要更改的部分放在注释块中。
import SwiftUI
import UserNotifications
enum Identifiers {
static let viewAction = "VIEW_IDENTIFIER"
static let readableCategory = "READABLE"
}
@main
struct MyApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
var body: some Scene {
WindowGroup {
TabView{
NavigationView{
ContentView()
}
.tabItem {
Label("Home", systemImage : "house")
}
}
}
}
}
class AppDelegate: NSObject, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
UNUserNotificationCenter.current().delegate = self// set the delegate
registerForPushNotifications()
return true
}
func application( // registers for notifications and gets token
_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
) {
let tokenParts = deviceToken.map { data in String(format: "%02.2hhx", data) }
let token = tokenParts.joined()
print("device token : \(token)")
}//handles sucessful register for notifications
func application( //handles unsucessful register for notifications
_ application: UIApplication,
didFailToRegisterForRemoteNotificationsWithError error: Error
) {
print("Failed to register: \(error)")
}//handles unsucessful register for notifications
func application( //handles notifications when app in foreground
_ application: UIApplication,
didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler:
@escaping (UIBackgroundFetchResult) -> Void
) {
guard let aps = userInfo["aps"] as? [String: AnyObject] else {
completionHandler(.failed)
return
}
print("new notification received")
}//handles notifications when app in foreground
func registerForPushNotifications() {
UNUserNotificationCenter.current()
.requestAuthorization(options: [.alert, .sound, .badge]) { [weak self] granted, _ in
print("permission granted: \(granted)")
guard granted else { return }
let viewAction = UNNotificationAction(
identifier: Identifiers.viewAction,
title: "Mark as read",
options: [.foreground])
let readableNotification = UNNotificationCategory(
identifier: Identifiers.readable,
actions: [viewAction2],
intentIdentifiers: [],
options: [])
UNUserNotificationCenter.current().setNotificationCategories([readableNotification])
self?.getNotificationSettings()
}
}
func getNotificationSettings() {
UNUserNotificationCenter.current().getNotificationSettings { settings in
guard settings.authorizationStatus == .authorized else { return }
DispatchQueue.main.async {
UIApplication.shared.registerForRemoteNotifications()
}
print("notification settings: \(settings)")
}
}
}
// MARK: - UNUserNotificationCenterDelegate
extension AppDelegate: UNUserNotificationCenterDelegate {
func userNotificationCenter(
_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void
) {
let userInfo = response.notification.request.content.userInfo
if let aps = userInfo["aps"] as? [String: AnyObject],
let newsItem = NewsItem.makeNewsItem(aps) {
(window?.rootViewController as? UITabBarController)?.selectedIndex = 1
if response.actionIdentifier == Identifiers.viewAction,
let url = URL(string: newsItem.link) {
let safari = SFSafariViewController(url: url)
window?.rootViewController?.present(safari, animated: true, completion: nil)
}
}
completionHandler()
}
}
// MARK: - UNUserNotificationCenterDelegate
extension AppDelegate: UNUserNotificationCenterDelegate {
func userNotificationCenter(
_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void
) {
let userInfo = response.notification.request.content.userInfo
if let aps = userInfo["aps"] as? [String: AnyObject],
/*
let newsItem = NewsItem.makeNewsItem(aps) {
(window?.rootViewController as? UITabBarController)?.selectedIndex = 1
if response.actionIdentifier == Identifiers.viewAction,
let url = URL(string: newsItem.link) {
let safari = SFSafariViewController(url: url)
window?.rootViewController?.present(safari, animated: true, completion: nil)
}
}
*/
completionHandler()
}
}
这是教程中的 NewsItem.swift 以防万一,但这是我不需要或不想使用的文件。
import Foundation
struct NewsItem: Codable {
let title: String
let date: Date
let link: String
@discardableResult
static func makeNewsItem(_ notification: [String: AnyObject]) -> NewsItem? {
guard
let news = notification["alert"] as? String,
let url = notification["link_url"] as? String
else {
return nil
}
let newsItem = NewsItem(title: news, date: Date(), link: url)
let newsStore = NewsStore.shared
newsStore.add(item: newsItem)
NotificationCenter.default.post(
name: NewsFeedTableViewController.refreshNewsFeedNotification,
object: self)
return newsItem
}
}
简化的内容视图
import SwiftUI
struct ContentView: View {
var body: some View {
VStack{
Text(DataForApp.welcomeText)
.font(.title)
.bold()
.multilineTextAlignment(.center)
.foregroundColor(.secondary)
.shadow(radius: 8 )
} .navigationTitle("My Mobile App")
}
}
现在我的目标是使用此 MyView,一旦用户点击“标记为已读”操作,我希望此视图显示。
import SwiftUI
struct MyView: View {
var body: some View {
Text("Notification text here")
}
}
显然 MyView 不包含它需要的任何东西,但我不想发布我在这里尝试过的代码,因为我尝试了 200 种不同的东西,由于它们都不起作用,我意识到我什至没有接近正确的轨道。
【问题讨论】:
-
{ "aps": { "alert": "Breking News!", "sound": "default", "link_url": "raywenderlich.com", "category": "READABLE" } } 这是我发送给测试的通知
标签: ios swiftui notifications action