iOS

UserNotifications frameworkについて

2017年3月29日

目次Category


UserNotification Frameworkについて

UserNotifications frameworkとは

なぜUserNotifications framework(UNNotification)を使用する必要があるのか?

iOS9までのUINotificationはiOS10では非推奨

UINotificationでできなかったことが実現可能

  1. アプリがforeground時にもNotification表示が可能
  2. 通知時の音源(曲)や画像が自由に変更可能
  3. 通知内にActionボタンを設定可能
  • タップしたボタンによって通知自体の動作(起動する・しない)が変更可能
  • タップしたボタンによってアプリ自体の動作も変更可能(起動画面の変更等)

 

今回作成するアプリの流れ

Un02

通知実装手順

本章では具体的な通知実装手順を紹介する。

1. 通知の許可(requestAuthorization)

2. 通知カテゴリ登録(UNNotificationCategory)

3. 通知アクション登録(UNNotificationAction)

4. 通知トリガ登録(UNNotificationTrigger)

5. 通知コンテンツ登録(UNNotificationCategory)

 

1.通知の許可(requestAuthorization)

UNUserNotificationCenterのrequestAuthorizationにて通知を許可する。

設定可能なUNAuthorizationOptionsは以下の4種類

  • budge : バッジ
  • sound : 音
  • alert : アラート
  • carplay : 車

 

以下、記述例(Swiftの場合)

let center = UNUserNotificationCenter.current()
center.requestAuthorization(options: [.alert, .sound]) { (granted, error) in
    // Enable or disable features based on authorization.
}

 

2.通知カテゴリ登録(UNNotificationCategory)

UNNotificationCategoryは通知のタイプと表示されるカスタムアクションを定義する。

UNNotificationCategoryの引数については以下となる。

  • identifier : カテゴリに割り当てられた一意の文字列
  • actions : 通知が表示されたときに表示するアクション
  • intentIdentifiers : このカテゴリの通知に関連するインテント
  • options : UNNotificationCategoryOptions設定

 

UNNotificationCategoryOptionsは以下の設定が可能

  • customDismissAction : UNUserNotificationCenterオブジェクトのデリゲートにdismissアクションを送信する。
  • allowInCarPlay : 通知をCarPlayに表示する。

 

以下、記述例(Swiftの場合)

func getCategory() -> UNNotificationCategory {
let category = UNNotificationCategory(
    identifier: "GENERAL",
    actions: [],
    intentIdentifiers: [],
    options: .customDismissAction)
  return category
}

 

3.通知アクション登録(UNNotificationAction)

UNNotificationActionは最大4つまでのアクションを設定可能

UNNotificationActionの引数については以下の通り

  • Identifier : アクションに割り当てられた一意の文字列
  • title : アクションボタンの表示タイトル
  • options : UNNotificationActionOptions設定

 

UNNotificationActionOptionsは以下の設定が可能

  • authenticationRequired : デバイスのロック解除
  • destructive : 破壊的な処理を通知
  • foreground : アプリをフォアグラウンドに表示

 

以下、記述例(Swiftの場合)

func getCategory() -> UNNotificationCategory {
  //Action定義
  let authAction = UNNotificationAction(identifier: "authentication",
    title: "認証", options: .authenticationRequired)
  let destAction = UNNotificationAction(identifier: "destructive",
    title: "閉じる", options: .destructive)
  let foreAction = UNNotificationAction(identifier: "foreAction",
    title: “アプリ起動”, options: .foreground)

  let category = UNNotificationCategory(
    identifier: "GENERAL",
    actions: [authAction, foreAction, destAction],
    intentIdentifiers: [],
    options: .customDismissAction)
  return category
}

 

4.通知トリガ登録(UNNotificationTrigger)

通知トリガを制御するためのUNNotificationTriggerは以下の4種類が存在する。

  • UNTimeIntervalNotificationTrigger : 指定した時間が経過すると、ローカル通知を配信
  • UNCalendarNotificationTrigger : 指定した日時に通知を配信
  • UNLocationNotificationTrigger : 指定された地理的な場所に到達した時に通知を配信
  • UNPushNotificationTrigger : APNSを使用して送信された時に通知(リモートPush)

 

以下、記述例(Swiftの場合)

10秒後に通知

func getTimerTrigger() -> (UNNotificationTrigger){
   let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 10, repeats: false)
   return trigger 
}

 

毎朝7時に通知

func getCalendarTrigger() -> (UNNotificationTrigger){
  // 毎朝7時に通知
  var dateInfo = DateComponents()
  dateInfo.hour = 7
  dateInfo.minute = 0
  let trigger = UNCalendarNotificationTrigger(dateMatching: dateInfo, repeats: false)
  return trigger
}

 

5.通知コンテンツ登録(UNNotificationContent)

UNNotificationContentは通知コンテンツの編集が可能

UNNotificationContentの主なプロパティは以下の通り

  • title : 通知のタイトル
  • subtitle : 通知のサブタイトル
  • body : 通知の本文
  • sound : 通知時の曲(音源)を設定(※注1)
  • categoryIdentifier : 通知時に使用するカテゴリIDを設定(※注2)
  • attachments : 通知で表示するイメージ画像を設定

 

以下、記述例(Swiftの場合)

func getContent() -> (UNNotificationContent){
  let content = UNMutableNotificationContent()
  content.title = "タイトル"
  content.subtitle = "サブタイトル"
  content.body = "ここに本文が入ります。\nいろいろ書けます。??"
  content.sound = UNNotificationSound.init(named: "yaz.mp3")
  content.categoryIdentifier = "GENERAL"
  if let url = Bundle.main.url(forResource: "yaz", withExtension: "png") {
    let attachment = try?
    UNNotificationAttachment(identifier: "attachment", url: url, options: nil)
    if let attachment = attachment {
      content.attachments = [attachment]
    }
  }
  return content
}

 

UNNotificationを使用する際の注意点

※注1)カスタムアラート音源について

nAppleの公式サイトには「aiff、wav、caf」が使用可能と記述されているがmp3も使用可能。ただしどの音源も演奏時間が30秒以下でないと音が鳴らないため注意。

※注2)アクションボタンの表示について

n公式サイトや他のサイトでは特に触れられていないが、UNNotificationContentのcategoryIdentifierにUNNotificationCategoryのidentifierと同じIDを設定しないとアクションボタンが設定されないため注意。

 

動作環境

今回サンプルコードを動作させた環境は以下の通り。

  • macOS Sierra 10.12.3
  • Xcode Version 8.2.1 (8C1002)
  • Simulator(Version 10.0)
  • iPhone7
  • iOS10.2(14C89)
  • Swift3

 

(付録)サンプルコード

import UIKit
import UserNotifications

class ViewController: UIViewController, UNUserNotificationCenterDelegate {
  override func viewDidLoad() {
    super.viewDidLoad()
  }
 
  @IBAction func setNotification(_ sender: UIButton) {
    //UNUserNotificationCenter登録
    setNotificationCenter()
  }
 
  /**
   UNUserNotificationCenter登録
  */
  func setNotificationCenter() {
    let center = UNUserNotificationCenter.current()
    
    //通知の許可
    requestAuthorization(center: center)
 
    //通知カテゴリの生成
    let category = getCategory()

    // UNUserNotificationCenterへの通知カテゴリの登録
    center.setNotificationCategories([category])
 
    // Contentの生成
    let content = getContent()
 
    //通知トリガの生成
    let trigger = getTimerTrigger()
 
    // リクエストの生成
    let request = UNNotificationRequest(identifier: "TimerAlarm", content: content, trigger: trigger)
 
    //UNUserNotificationCenterへのリクエストの登録
    center.add(request) { (error : Error?) in
      if let theError = error {
        print(theError.localizedDescription)
      }
    }
  }
 
  /**
   通知の許可
   - parameter center: UNUserNotificationCenter
  */
  func requestAuthorization(center: UNUserNotificationCenter) {
    center.requestAuthorization(
      options: [.badge, .sound, .alert], completionHandler: {(granted, error) in
        if error != nil {
          debugPrint("通知許可失敗")
          return
        }
 
        if granted {
          debugPrint("通知許可")
          center.delegate = self
        } else {
          debugPrint("通知拒否")
        }
      })
  }
 
  /**
   通知コンテンツ登録
   - parameter center: UNUserNotificationCenter
   - returns: UNNotificationContent
  */
  func getContent() -> (UNNotificationContent){
    let content = UNMutableNotificationContent()
    content.title = "タイトル"
    content.subtitle = "サブタイトル"
    content.body = "ここに本文が入ります。\nいろいろ書けます。??"
    content.sound = UNNotificationSound.init(named: "yaz.mp3")
 
    if let url = Bundle.main.url(forResource: "yaz", withExtension: "png") {
      let attachment = try? UNNotificationAttachment(identifier: "attachment", url: url, options: nil)
      if let attachment = attachment {
        content.attachments = [attachment]
      }
    }
    content.categoryIdentifier = "GENERAL"
    return content
  }
 
  /**
   通知カテゴリ登録
   - returns: UNNotificationCategory
  */
  func getCategory() -> UNNotificationCategory {
 
    //Action定義
    let authAction = UNNotificationAction(identifier: "authentication",
      title: "認証",
      options: .authenticationRequired)
    let destAction = UNNotificationAction(identifier: "destructive",
      title: "閉じる",
      options: .destructive)
    let foreAction = UNNotificationAction(identifier: "foreAction",
      title: "アプリ起動",
      options: .foreground)
 
    let category = UNNotificationCategory(
      identifier: "GENERAL",
      actions: [authAction, foreAction, destAction],
      intentIdentifiers: [],
      options: .customDismissAction)
    return category
  }
 
  /**
   通知トリガ登録(UNTimeIntervalNotificationTrigger)
   - returns: UNNotificationTrigger
  */
  func getTimerTrigger() -> (UNNotificationTrigger){
    let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 10, repeats: false)
    return trigger
  }
 
  /**
   通知トリガ登録(UNCalendarNotificationTrigger)
   - returns: UNNotificationTrigger
  */
  func getCalendarTrigger() -> (UNNotificationTrigger){
    var dateInfo = DateComponents()
    dateInfo.hour = 7
    dateInfo.minute = 0
    let trigger = UNCalendarNotificationTrigger(dateMatching: dateInfo, repeats: false)
    return trigger
  }
 
  /**
  アプリがフォアグラウンド時に通知された時に呼ばれる。
  */
  func userNotificationCenter(_ center: UNUserNotificationCenter
    , willPresent notification: UNNotification
    , withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
    completionHandler([.alert, .sound]) // 通知バナー表示、通知音の再生を指定
  }
}

 

この記事を書いた人

嶋脇真樹

masaki_shimawaki