Skip to content

Instantly share code, notes, and snippets.

@prafullakumar
Last active February 10, 2023 17:10
Show Gist options
  • Save prafullakumar/17b169885bb8defdd24bf9a7cdd84188 to your computer and use it in GitHub Desktop.
Save prafullakumar/17b169885bb8defdd24bf9a7cdd84188 to your computer and use it in GitHub Desktop.
import SwiftUI
import os
@main
struct ios14DemoApp: App {
@StateObject var notificationCenter = NotificationCenter()
@UIApplicationDelegateAdaptor private var appDelegate: AppDelegate
var body: some Scene {
WindowGroup {
LocalNotificationDemoView(notificationCenter: notificationCenter)
}
}
}
class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
return true
}
//No callback in simulator -- must use device to get valid push token
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
print(deviceToken)
}
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
print(error.localizedDescription)
}
}
class NotificationCenter: NSObject, ObservableObject {
@Published var dumbData: UNNotificationResponse?
override init() {
super.init()
UNUserNotificationCenter.current().delegate = self
}
}
extension NotificationCenter: UNUserNotificationCenterDelegate {
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler([.alert, .sound, .badge])
}
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
dumbData = response
completionHandler()
}
func userNotificationCenter(_ center: UNUserNotificationCenter, openSettingsFor notification: UNNotification?) { }
}
class LocalNotification: ObservableObject {
init() {
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound]) { (allowed, error) in
//This callback does not trigger on main loop be careful
if allowed {
os_log(.debug, "Allowed")
} else {
os_log(.debug, "Error")
}
}
}
func setLocalNotification(title: String, subtitle: String, body: String, when: Double) {
let content = UNMutableNotificationContent()
content.title = title
content.subtitle = subtitle
content.body = body
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: when, repeats: false)
let request = UNNotificationRequest.init(identifier: "localNotificatoin", content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request, withCompletionHandler: nil)
}
}
struct LocalNotificationDemoView: View {
@StateObject var localNotification = LocalNotification()
@ObservedObject var notificationCenter: NotificationCenter
var body: some View {
VStack {
Button("schedule Notification") {
localNotification.setLocalNotification(title: "title",
subtitle: "Subtitle",
body: "this is body",
when: 10)
}
if let dumbData = notificationCenter.dumbData {
Text("Old Notification Payload:")
Text(dumbData.actionIdentifier)
Text(dumbData.notification.request.content.body)
Text(dumbData.notification.request.content.title)
Text(dumbData.notification.request.content.subtitle)
}
}
}
}
extension UIApplicationDelegate {
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
print("Successfully registered for notifications!")
}
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
print("Failed to register for notifications: \(error.localizedDescription)")
}
}
struct PageView: View {
@State private var selection = 0
@State private var localSelectionState = 0
var body: some View {
TabView(selection: $selection) {
ForEach(0..<30) { i in
ZStack {
Color.secondary
Text("Row: \(i)").foregroundColor(Color(UIColor.systemBackground))
}.clipShape(RoundedRectangle(cornerRadius: 10.0, style: .continuous))
//.scaleEffect((selection == i) ? 1.0 : 0.8)
}
.padding(.all, 10)
}.onChange(of: selection, perform: { value in
withAnimation {
localSelectionState = value
}
})
.frame(width: UIScreen.main.bounds.width - 200, height: 200)
.tabViewStyle(PageTabViewStyle())
}
}
struct PageView_Previews: PreviewProvider {
static var previews: some View {
ScrollView {
LazyHStack {
PageView()
}
}
}
}
@viktorsec
Copy link

Hi I'm new to Swift so I might be very well wrong, but this didn't work for me as-is. My view didn't update on NotificationCenter.dumbData changes, so I couldn't react to the notification being tapped.

I managed to fix it by adding @Published before the var on line #38. Also, I think that the first two userNotificationCenter methods (#47, #50) should call completionHandler(). Are these changes correct?

Thanks for the gist!

@grosch
Copy link

grosch commented Dec 12, 2020

Not calling completionHandler is very bad. The RayWenderlich.com book on Push Notifications is going through final editing for version 3 right now, and it's been completely redone to use SwiftUI in all the examples.

@prafullakumar
Copy link
Author

@viktorsec yes you are right, Updated the gist :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment