Swift・iOS

Swiftを中心に学んだことを記録に残すブログです。技術に関係ない記事もたまに書いています。

【Swift】User Notifications frameworkでローカル通知機能の実装(バックグラウンド/フォアグラウンドでの表示)

■はじめに

iOS 10以降で使えるUserNotificationsでローカル通知の実装をしてみました。

 

とはいえ、表題の内容には既にネット上に詳しい説明をしている記事が多くあります。

実装してみたい方は、まずは本記事の末に記載した参考記事をご覧ください。参考記事で理解できた方は以下読まなくて大丈夫です。

 

■既に記事があるのになぜ書くのか

私が実際にコードを書いてみた時に「参考記事は各機能やその役割に関しては詳細に書かれているけど、実際動かそうとした時に、どこにどう書けばよいか部分的にちょっとわかりにくい箇所があるかも・・・」と感じたためです。

経験者の方からすると、参考記事は丁寧すぎるくらい説明されていると思いますが、初心者が気軽に試してみることができるように、今回試したことを残すことは無駄(他の記事との重複)にはならないかなと思いました。

 

■今回の実装に関して

iOS 10以降のNotificationの基本 - Qiitaの記事を参考にさせていただいた上で、以下変更を加えて実装してみました。

 

・フォアグラウンドでも通知を表示する機能の追加

・UISegmentedControlは使用せず、10秒後に通知が飛ぶように変更

※通知内容やコメントに関しては日本語に変更しています。

 

■実装内容

どこにどの内容を書けばよいかわかるよう、通知に関する記述箇所に絞らずにあえて全体のコードを載せます。

「Main.storyboard」に「Button」を1つ配置し、「setNotification」という名称のActionボタンをまずは作りましょう。

その後は以下の通りに記述します。各文章がそれぞれどのような機能や定義なのかは

UserNotifications | Apple Developer Documentationと照らし合わせながら確認していくとよいかもしれません。

 

(1)AppDelegate.swift

※UserNotificationsのimport忘れずに!

import UIKit
import UserNotifications

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    
    var window: UIWindow?
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        
        // アプリのバッジの更新、サウンド、アラートの通知に関してユーザへ確認
        let center = UNUserNotificationCenter.current()
        center.requestAuthorization(options: [.alert, .badge, .sound]) {(granted, error) in
            if granted {
                print("許可する")
            } else {
                print("許可しない")
            }
        }
        return true
    }
    
    func applicationWillResignActive(_ application: UIApplication) {
        // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
        // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
    }
    
    func applicationDidEnterBackground(_ application: UIApplication) {
        // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
        // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
    }
    
    func applicationWillEnterForeground(_ application: UIApplication) {
        // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
    }
    
    func applicationDidBecomeActive(_ application: UIApplication) {
        // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
    }
    
    func applicationWillTerminate(_ application: UIApplication) {
        // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
    }
}

 

 (2)ViewController.swift

※「UserNotifications」のimportと「UNUserNotificationCenterDelegate」プロトコルの宣言を忘れずに!

import UIKit
import UserNotifications

class ViewController: UIViewController, UNUserNotificationCenterDelegate {
    
    // 通知を作成
    @IBAction func setNotification(_ sender: Any) {
        // タイトル、本文、サウンド設定の保持
        let content = UNMutableNotificationContent()
        content.title = "時間です"
        content.subtitle = "10秒経過しました"
        content.body = "タップしてアプリを開いてください"
        content.sound = UNNotificationSound.default()
        
        // seconds後に起動するトリガーを保持
        let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 10, repeats: false)
        
        // 識別子とともに通知の表示内容とトリガーをrequestに内包する
        let request = UNNotificationRequest(identifier: "Timer", content: content, trigger: trigger)
        
        // UNUserNotificationCenterにrequestを加える
        let center = UNUserNotificationCenter.current()
        center.delegate = self
        center.add(request) { (error) in
            if let error = error {
                print(error.localizedDescription)
            }
        }
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    // フォアグラウンドの場合でも通知を表示する
    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        completionHandler([.alert, .badge, .sound])
    }
}

 

■おわりに

基本的には同様の内容の記事を書くことは誰も幸せにならないという認識はあるものの、もしかすると解らずに困っている人がいるかもと思い記事に残しました。

今回動かしてみた実装内容は、実際のアプリでは通知に関する機能を1つのファイルに分けて実装するなど違いがあるかと思いますので、別途実践的な内容にチャレンジしてみようと思います。

 

■参考

UserNotifications | Apple Developer Documentation

iOS 10以降のNotificationの基本 - Qiita

User Notifications frameworkでローカル通知を送ってみる - しめ鯖日記

[iOS 10] User Notifications framework を使用して時限式のローカル通知を作成する #wwdc | Developers.IO