Designing Notifications 참조

class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {

    func application(_ application: UIApplication,
                     didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        UIApplication.shared.registerForRemoteNotifications()
        UNUserNotificationCenter.current().delegate = self
        return true
    }

// 실패시 콜백
func application(_ application: UIApplication,
                   didFailToRegisterForRemoteNotificationsWithError error: Error) {
    // The token is not currently available.
    print("Remote notification is unavailable: \\\\(error.localizedDescription)")
}

// 성공시 콜백
func application(_ application: UIApplication,
                   didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
     // Forward the token to your provider, using a custom method.
     self.forwardTokenToServer(token: deviceToken)
}

func forwardTokenToServer(token: Data) {
    let tokenComponents = token.map { data in String(format: "%02.2hhx", data) }
    let deviceTokenString = tokenComponents.joined()
    let queryItems = [URLQueryItem(name: "deviceToken", value: deviceTokenString)]
    var urlComps = URLComponents(string: "www.example.com/register")!
    urlComps.queryItems = queryItems
    guard let url = urlComps.url else {
        return
    }

    let task = URLSession.shared.dataTask(with: url) { data, response, error in
        // Handle data
    }

    task.resume()
	}
}

/// 노티 권한설정
@IBAction func subscribeToNotifications(_ sender: Any) {
    let userNotificationCenter = UNUserNotificationCenter.current()
    userNotificationCenter.requestAuthorization(options: [.alert, .sound, .badge]) { (granted, error) in
        print("Permission granted: \\\\(granted)")
    }
}

{
    "aps" : {
       "alert" : {
            "title" : "Check out our new special!",
            "body" : "Avocado Bacon Burger on sale"
        },
        "sound" : "default",
        "badge" : 1,
   },
		
	// 이하 커스텀 데이터
    "special" : "avocado_bacon_burger",
    "price" : "9.99"
}

func userNotificationCenter(_ center: UNUserNotificationCenter,
                            didReceive response: UNNotificationResponse,
                            withCompletionHandler completionHandler: @escaping () -> Void) {
    let userInfo = response.notification.request.content.userInfo
    guard let specialName = userInfo["special"] as? String,
          let specialPriceString = userInfo["price"] as? String,
          let specialPrice = Float(specialPriceString) else {
        // Always call the completion handler when done.
        completionHandler()
        return
    }

    let item = Item(name: specialName, price: specialPrice)
		addItemToCart(item)
  	showCartViewController()
    completionHandler()
 }

// UNUserNotificationDelegate 불필요
class AppDelegate: UIResponder, UIApplicationDelegate {

    func application(_ application: UIApplication,
                     didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
       UIApplication.shared.registerForRemoteNotifications()
       return true
    }

{
    "aps" : {
       "content-available" : 1
    },
    "myCustomKey" : "myCustomData"
}

func application(_ application: UIApplication,
                     didReceiveRemoteNotification userInfo: [AnyHashable : Any],
                     fetchCompletionHandler completionHandler:
                     @escaping (UIBackgroundFetchResult) -> Void) {
    guard let url = URL(string: "www.example.com/todays-menu") else {
        completionHandler(.failed)
        return
    }

    let task = URLSession.shared.dataTask(with: url) { data, response, error in
        guard let data = data else {
            completionHandler(.noData)
            return
        }
  
        updateMenu(withData: data)
        completionHandler(.newData)
    }
}