Skip to content

Instantly share code, notes, and snippets.

@KentarouKanno
Last active November 20, 2019 21:06
Show Gist options
  • Star 20 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save KentarouKanno/d7c7768deea70076264f2208a878de68 to your computer and use it in GitHub Desktop.
Save KentarouKanno/d7c7768deea70076264f2208a878de68 to your computer and use it in GitHub Desktop.
UNUserNotification

UNUserNotification

@available(iOS 10.0, *)
import UserNotifications

NSUserNotification API Reference
UNNotificationSound API Reference
UNUserNotificationCenter API Reference

参考URL:
iOS 10 User Notifications Framework実装まとめ

ローカル通知

★ 通知の許可を求める

// current() メソッドを使用してシングルトンオブジェクトを取得
let center = UNUserNotificationCenter.current()

// 通知の使用許可をリクエスト
center.requestAuthorization(options: [.alert, .sound]) { (granted, error) in
    
    print(granted) // 許可している場合はtrue, していない場合はfalse
    print(error ?? "")   // nil
    
    // 許可アラートが出た場合はボタンを選択時にBlockが呼ばれる,その後は即時に呼ばれる
}

★ UNAuthorizationOptions

/*
badge
sound
alert
carPlay
*/

★ 時限式のローカル通知を作成する

// UNMutableNotificationContentを作成
let content = UNMutableNotificationContent()
content.title = "iOS10"
content.subtitle = "SubTitle"
content.body  = "UNUserNotificationCenter!"
content.badge = 2
content.userInfo = ["A": "a"]
content.sound = UNNotificationSound.default()
// content.sound = UNNotificationSound(named: "sample.m4a") 

// 5秒後に発火するUNTimeIntervalNotificationTriggerを作成、
let trigger = UNTimeIntervalNotificationTrigger.init(timeInterval: 5, repeats: false)

// identifier, content, trigger からUNNotificationRequestを作成
let request = UNNotificationRequest.init(identifier: "FiveSecondNotification", content: content, trigger: trigger)

// UNUserNotificationCenterにrequestを追加
let center = UNUserNotificationCenter.current()
center.add(request)

★ 画像を添付する場合

let fileURL = URL(fileURLWithPath: Bundle.main().pathForResource("apple", ofType: "png")!)
let attachment = try! UNNotificationAttachment(identifier: "image", url: fileURL, options: nil)
content.attachments = [attachment]

★ 指定日時に発火するローカル通知を作成する

// UNMutableNotificationContentを作成
let content = UNMutableNotificationContent()
content.title = "Hello!"
content.body  = "It's time!"
content.sound = UNNotificationSound.default()

// UNCalendarNotificationTriggerを作成
let date = DateComponents(month:7, day:7, hour:12, minute:0)
let trigger = UNCalendarNotificationTrigger.init(dateMatching: date, repeats: false)

// id, content, triggerからUNNotificationRequestを作成
let request = UNNotificationRequest.init(identifier: "CalendarNotification", content: content, trigger: trigger)

// UNUserNotificationCenterにrequestを追加
let center = UNUserNotificationCenter.current()
center.add(request)

// リピート有りの場合
// let date = DateComponents(hour:8, minute:30)
// let trigger = UNCalendarNotificationTrigger.init(dateMatching: date, repeats: true)

// 次の発火日時を取得する
let nextTriggerDate = trigger.nextTriggerDate()
print(nextTriggerDate)

★ 位置情報に基づいて発火するローカル通知を作成する

// UNMutableNotificationContentを作成
let content = UNMutableNotificationContent()
content.title = "Hello!"
content.body  = "Enter Headquarter"
content.sound = UNNotificationSound.default()

// UNLocationNotificationTriggerを作成
let coordinate = CLLocationCoordinate2DMake(35.697275, 139.774728)
let region = CLCircularRegion.init(center: coordinate, radius: 1000.0, identifier: "Headquarter")
region.notifyOnEntry = true;
region.notifyOnExit = false;
let trigger = UNLocationNotificationTrigger.init(region: region, repeats: false)

// id, content, triggerからUNNotificationRequestを作成
let request = UNNotificationRequest.init(identifier: "LocationNotification", content: content, trigger: trigger)

// UNUserNotificationCenterにrequestを追加
let center = UNUserNotificationCenter.current()
center.add(request)

★ 登録した通知を変更する(同じidentifierを使用して再登録する) print("didReceive Local Notification")

// 通知の定義
let updatedRequest = UNNotificationRequest(identifier: "CalendarNotification", content: content, trigger: trigger)

// 通知の登録(更新)
UNUserNotificationCenter.current().add(updatedRequest) { (error) in
    print(error) // 正常に更新された場合 nil
}

★ アプリがForegroundで通知が来たことをDelegateメソッドで感知する

// UNUserNotificationCenterDelegateを継承する
class ViewController: UIViewController, UNUserNotificationCenterDelegate 

let center = UNUserNotificationCenter.current()
// デリゲートを設定
center.delegate = self;
center.add(request)

// アプリが Foreground の時に通知を受け取った時に呼ばれるメソッド
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: (UNNotificationPresentationOptions) -> Void) {
    print("fire! notification ID:\(notification.request.identifier)")
    
    // Foregroundでも上から出てくる通知を出したいときは以下を記述
    // 通知バナー表示、通知音の再生を指定
    completionHandler([.alert, .sound])  
}

★ アプリがBackgroundで通知タップ、通知センターでの通知タップで起動したことをDelegateメソッドで感知する
※ アプリが終了している場合はAppDelegateのlaunchOptionsでdelegateを設定しておかないと取得できない。

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        
    let center = UNUserNotificationCenter.current()
    // デリゲートを設定
    center.delegate = self;
    
    return true
}

func userNotificationCenter(_ center: UNUserNotificationCenter,
                            didReceive response: UNNotificationResponse,
                            withCompletionHandler completionHandler: @escaping () -> Void) {
    
    // 通知の情報を取得
    let notification = response.notification
    
    // リモート通知かローカル通知かを判別
    if notification.request.trigger is UNPushNotificationTrigger {
        print("didReceive Push Notification")
    } else {
        // UserInfoを取得
        print(notification.request.content.userInfo)
        print("didReceive Local Notification")
    }
    
    // 通知の ID を取得
    print("notification.request.identifier: \(notification.request.identifier)")
    
    // 処理完了時に呼ぶ
    completionHandler()
}

★ 未配信の通知一覧を取得する

let center = UNUserNotificationCenter.current()
center.getPendingNotificationRequests { (requests: [UNNotificationRequest]) in
    for request in requests {
        print(request)
        print("---------------")
    }
}

★ 特定の未配信の通知を削除する(identifierを指定)

let center = UNUserNotificationCenter.current()

center.getPendingNotificationRequests { (requests: [UNNotificationRequest]) in
    for request in requests {
        if request.identifier == "CalendarNotification" {
            center.removePendingNotificationRequests(withIdentifiers: [request.identifier])
        }
    }
}

★ 全ての未配信の通知を削除する

let center = UNUserNotificationCenter.current()
center.removeAllPendingNotificationRequests()

リモート通知

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    
    let center = UNUserNotificationCenter.current()
    center.requestAuthorization([.alert, .sound]) { (granted, error) in
        
        // 許可している場合はtrue, していない場合はfalse
        if granted {
            application.registerForRemoteNotifications()
        }
    }
    
    return true
}

通知センター

★ 通知センターにある通知一覧を取得する

let center = UNUserNotificationCenter.current()
center.getDeliveredNotifications { (notifications: [UNNotification]) in
    for notification in notifications {
        print(notification)
        print("---------")
    }
}

★ 通知センターから特定の通知を削除する

let center = UNUserNotificationCenter.current()

center.getDeliveredNotifications {  (notifications: [UNNotification]) in
    for notification in notifications {
        if notification.request.identifier == "FiveSecondNotification" {
            center.removeDeliveredNotifications(withIdentifiers: [notification.request.identifier])
        }
    }
}

★ 通知センターの通知を全て削除する

let center = UNUserNotificationCenter.current()
center.removeAllDeliveredNotifications()

通知にアクションボタンを配置する

// -----AppDelegate -----

import UIKit
import UserNotifications

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?


    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        
        
        if #available(iOS 10.0, *) {
            // iOS 10
            let center = UNUserNotificationCenter.current()
            center.requestAuthorization(options: [.badge, .sound, .alert], completionHandler: { (granted, error) in
                if error != nil {
                    return
                }
                
                if granted {
                    debugPrint("通知許可")
                } else {
                    debugPrint("通知拒否")
                }
            })
            
        } else {
            // iOS 9
            let settings = UIUserNotificationSettings(types: [.badge, .sound, .alert], categories: nil)
            UIApplication.shared.registerUserNotificationSettings(settings)
        }
        return true
    }
}

// -----ViewController -----

import UIKit
import UserNotifications

enum ActionIdentifier: String {
    case attend
    case absent
}

class ViewController: UIViewController, UNUserNotificationCenterDelegate {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
    }
    
    @IBOutlet weak var a: UIButton!
    
    @IBAction func g(_ sender: AnyObject) {
        
        let attend = UNNotificationAction(identifier: ActionIdentifier.attend.rawValue,
                                          title: "出席", options: [])
        
        let absent = UNNotificationAction(identifier: ActionIdentifier.absent.rawValue,
                                          title: "欠席",
                                          options: [])
        
        
        let category = UNNotificationCategory(identifier: "message", actions: [attend, absent], intentIdentifiers:  [], options: [])
    
        UNUserNotificationCenter.current().setNotificationCategories([category])
        UNUserNotificationCenter.current().delegate = self
        
        
        let content = UNMutableNotificationContent()
        content.title = "出席確認"
        content.body = "今日のイベントに参加しますか?"
        content.sound = UNNotificationSound.default()
        
        // categoryIdentifierを設定
        content.categoryIdentifier = "message"
        
        // 5秒後
        let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: false)
        let request = UNNotificationRequest(identifier: "FiveSecond",
                                            content: content,
                                            trigger: trigger)
        
        UNUserNotificationCenter.current().add(request, withCompletionHandler: nil)
    }
    
    
    @available(iOS 10.0, *)
    func userNotificationCenter(_ center: UNUserNotificationCenter,
                                didReceive response: UNNotificationResponse,
                                withCompletionHandler completionHandler: @escaping () -> Swift.Void) {
        
        switch response.actionIdentifier {
        case ActionIdentifier.attend.rawValue:
            debugPrint("出席します")
        case ActionIdentifier.absent.rawValue:
            debugPrint("欠席します")
        default:
            ()
        }
        
        completionHandler()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        
    }
}

★ UserInfoを便利に扱うための構造体

struct NotificationPayload {
    let json: JSON
    private var aps: JSON { return json["aps"] }
    var alert: String? { return aps["alert"].string }
    var badge: Int? { return aps["badge"].int }
    var sound: String? { return aps["sound"].string }
    var contentAvailable: Int? { return aps["content-available"].int }
    var newsId: Int32? { return json["news_id"].int32 }
    var notificationId: Int32? { return json["notification_id"].int32 }
    
    init(userInfo: [AnyHashable : Any]) {
        json = JSON(userInfo)
    }
}

// 使い方

let payload = NotificationPayload(userInfo: userInfo)
if let badge = payload.badge {
            
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment