通知を表示する（ローカル通知）（UIKit::UIApplication.scheduleLocalNotification）

# ローカル通知

## 通知タイプ登録

通知を受け取ったときにアプリケーションが表示するUI要素（アイコンに添えるバッジ・鳴らすサウンド・表示する警告）を指定しないといけない
Noneだと、システムは画面に何も表示せず、アプリケーションにプッシュする

registerUserNotificationSettings:メソッドを初めて呼び出した時点で、登録したタイプの通知許可ダイアログが表示され、ユーザが応答すると非同期でUIApplicationDelegateオブジェクトのapplication:didRegisterUserNotificationSettings:メソッドを呼び出す（引数にユーザが許可した通知タイプが渡される）
ユーザは設定をいつでも変更できるので、通知を表示する都度、currentUserNotificationSettingsで設定を確認する必要あり

```swift:NotificationManager.swift
import UIKit

public class NotificationManager: NSObject {
    
    func setNotification(
        fireDate fireDate: NSDate? = nil,
                 timeZone: NSTimeZone? = nil,
                 repeatInterval: NSCalendarUnit = NSCalendarUnit.init(rawValue: 0),
                 repeatCalendar: NSCalendar? = nil,
                 alertAction: String? = nil,
                 alertBody: String? = nil,
                 alertTitle: String? = nil,
                 hasAction: Bool = true,
                 applicationIconBadgeNumber: Int = 0,
                 soundName: String? = nil,
                 userInfo: NSDictionary? = nil)
    {
        let settings = UIUserNotificationSettings(forTypes: [.Alert, .Badge, .Sound], categories: nil)
        
        UIApplication.sharedApplication().registerUserNotificationSettings(settings)
    }
}
```

## ローカル通知の作成・設定・スケジューリング

- UILocalNotificationオブジェクトを割り当て、初期化
- fireDateプロパティ設定
 - nilや過去の日時だと登録と同時に通知
- timeZoneプロパティ設定
 - nilだとGMT
 - 現在のロケールに設定した場合、異なるタイムゾーンに渡って移動したときに、自動的に配信日を調整
- repeatIntervalプロパティ設定
 - 初期値は0（1回限り）
 - 1分未満はサポートされていない
- repeatCalendarプロパティ設定
 - 参照するカレンダー
 - 初期値はnilでNSCalendar.currentCalendar()
- alertActionプロパティ設定
 - アクションボタンやスライダのタイトル
- alertBodyプロパティ設定
- alertTitleプロパティ設定
　- Apple Watchに表示
- hasActionプロパティ設定
 - アクションボタンやスライダの表示
- applicationIconBadgeNumberプロパティ設定
 - アイコン上にバッジとして添える数字
- soundNameプロパティ設定
 - 30秒を超える音源はサポートされていない
 - 初期値はnil（音なし）
 - 単独で使わず、警告メッセージまたはバッジを併用
- userInfoプロパティ設定
 - 通知にカスタムデータを添える
- scheduleLocalNotification:メソッドかpresentLocalNotificationNow:メソッドでスケジューリング

```swift:NotificationManager.swift
        UIApplication.sharedApplication().registerUserNotificationSettings(settings)
        
        let localNotification = UILocalNotification.init()
        localNotification.fireDate = fireDate
        localNotification.timeZone = timeZone
        localNotification.repeatInterval = repeatInterval
        localNotification.repeatCalendar = repeatCalendar
        localNotification.alertAction = alertAction
        localNotification.alertBody = alertBody
        localNotification.alertTitle = alertTitle
        localNotification.hasAction = hasAction
        localNotification.applicationIconBadgeNumber = applicationIconBadgeNumber
        localNotification.soundName = soundName
        if let info = userInfo {
            localNotification.userInfo = info as [NSObject : AnyObject]
        }
        
        UIApplication.sharedApplication().scheduleLocalNotification(localNotification)
```

```swift:ViewController.swift
class ViewController: UIViewController {
    
    var notificationManager: NotificationManager = NotificationManager.init()

    override func viewDidLoad() {
        super.viewDidLoad()
        
        notificationManager.setNotification(fireDate: NSDate(), timeZone: NSTimeZone.localTimeZone(), repeatInterval: NSCalendarUnit.Minute, alertAction: "Alert Action", alertBody: "Alert Body", applicationIconBadgeNumber: 1, soundName: UILocalNotificationDefaultSoundName)
```

*スケジューリングされた特定の通知をキャンセルするには、UIApplication.sharedApplication().cancelLocalNotification:を呼び出す
すべての通知をキャンセルするには、UIApplication.sharedApplication().cancelAllLocalNotifications:を呼び出す
これらのメソッドはともに、現在表示されている通知警告もプログラム上で閉じる*

## 通知に応じてアプリケーションが起動された場合の処理

```swift:AppDelegate.swift
    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        
        if let options = launchOptions {
            let localNotification = options[UIApplicationLaunchOptionsLocalNotificationKey] as! UILocalNotification
            if let userInfo = localNotification.userInfo {
                if let value = userInfo["key"] {
                    print("value for key: \(String(value))")
                }
            }
            application.cancelLocalNotification(localNotification)
            application.applicationIconBadgeNumber = localNotification.applicationIconBadgeNumber - 1
        }
```

## フォアグラウンドで動作中の場合の処理

```swift:AppDelegate.swift
            application.applicationIconBadgeNumber = localNotification.applicationIconBadgeNumber - 1
        }
        
        return true
    }
    
    func application(application: UIApplication, didReceiveLocalNotification notification: UILocalNotification) {
        if let userInfo = notification.userInfo {
            if let value = userInfo["key"] {
                print("value for key: \(value)")
            }
        }
        application.applicationIconBadgeNumber = notification.applicationIconBadgeNumber - 1
    }
```

## 参考情報

[Local および Push Notification プログラミングガイド](https://developer.apple.com/jp/documentation/RemoteNotificationsPG.pdf)
[UILocalNotification Class Reference](https://developer.apple.com/library/ios/documentation/iPhone/Reference/UILocalNotification_Class/)