Swift転職なら=>【LevTech】
↑クリックして拡大
↑クリックして拡大
↑クリックして拡大
↑クリックして拡大

頭痛が減ったので共有です!

rebuild.fmを応援しています!

HOME > UILocalNotification

UILocalNotification

UILocalNotificationでローカル通知を行います。ネットワークを介するRemoteNotificationとは違います。 iPhone端末上で時刻日付が管理され通知してくれます。

UILocalNotificationのクラス階層

NSObject

UILocalNotification

参考Appleサイト(英語): UIKit Framework Reference UILocalNotification Class Reference
参考:iOS8でUILocalNotificationの通知を受け取る

Notificationを登録する、受け取る。



  //ApDelegate.swifの起動時に呼ばれる関数
  func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        //Notification登録前のおまじない。テストの為、現在のノーティフケーションを削除します
        UIApplication.sharedApplication().cancelAllLocalNotifications();
        
        //Notification登録前のおまじない。これがないとpermissionエラーが発生するので必要です。
        application.registerUserNotificationSettings(UIUserNotificationSettings(forTypes: UIUserNotificationType.Sound | UIUserNotificationType.Alert | UIUserNotificationType.Badge, categories: nil))
        
        //以下で登録処理
        var notification = UILocalNotification()
        notification.fireDate = NSDate(timeIntervalSinceNow: 5);//5秒後
        notification.timeZone = NSTimeZone.defaultTimeZone()
        notification.alertBody = "swift-saralymanからの通知だよ"
        notification.alertAction = "OK"
        notification.soundName = UILocalNotificationDefaultSoundName
        UIApplication.sharedApplication().scheduleLocalNotification(notification);
        
        return true
    }
    //上記のNotificatioを5秒後に受け取る関数
    func application(application: UIApplication, didReceiveLocalNotification notification: UILocalNotification) {
        
        var alert = UIAlertView();
        alert.title = "受け取りました";
        alert.message = notification.alertBody;
        alert.addButtonWithTitle(notification.alertAction!);
        alert.show();
        
    }

上記をAppDelegate.swftに貼り付けていただければ5秒後に以下ポップアップが表示されます

Localnotificationサンプル画像

ただし、上の例はアプリがフォアグランドにいて現在使用中の場合の通知の受け取り方です。その他アプリがアクティブじゃない場合アプリが起動自体していない場合のパターンも以下説明します


メモ:どうやらdateWithTimeIntervalSinceNowがswiftからなくなっているので代わりに以下を利用します。五秒後に実行。

[NSDate dateWithTimeIntervalSinceNow:(5)]

NSDate(timeIntervalSinceNow: 5)


毎日同じ時間に通知を出す方法(毎朝8時に実行)

参考:How to schedule a same local notification in swift
参考:Create local notification and fire at certain time every day (Swift)



        let now = NSDate()
        println(now);// -> 2015-09-15 23:06:47 +0000
        let calendar = NSCalendar(identifier: NSCalendarIdentifierGregorian)
        var comps:NSDateComponents = calendar!.components(NSCalendarUnit.HourCalendarUnit|NSCalendarUnit.MinuteCalendarUnit|NSCalendarUnit.SecondCalendarUnit,fromDate: now)
        comps.calendar = calendar;
        comps.hour = 8;
        
        let now2 = comps.date;
        println(now2);// -> Optional(0000-12-31 22:47:48 +0000)
        
        var notification = UILocalNotification()
        notification.alertBody = "hogehoge"
        notification.timeZone = NSTimeZone.defaultTimeZone();
        notification.fireDate = now2;
        notification.repeatInterval = NSCalendarUnit.CalendarUnitDay;
        UIApplication.sharedApplication().scheduleLocalNotification(notification)
        
        

NSDateComponentsには必要な情報をマスクします。今回は年月日は不要なので、時間(何時何分何秒)だけを取得している例です

スケジュールをセットすると以下のログが出力されます


 Attempting to schedule a local notification {fire date = Monday, January 1, 1 at 8:09:07 AM GMT+09:18:59, 
 time zone = Asia/Tokyo (GMT+9) offset 32400, repeat interval = NSCalendarUnitDay, 
 repeat count = UILocalNotificationInfiniteRepeatCount, 
 next fire date = Thursday, September 17, 2015 at 8:09:07 AM Japan Standard Time, 
 user info = (null)} with an alert but haven't received permission from the user to display alerts

上記 haven't received permissionが表示されていると、通知許可が行われていないのでその場合はこちら(このページの下)に 記載があるのでご参照ください。


毎月同じ日の同じ時間に通知を出す方法(3日の毎朝8時に実行)


        let now = NSDate()
        println(now);// -> 2015-09-17 22:08:42 +0000
        let calendar = NSCalendar(identifier: NSCalendarIdentifierGregorian)
        var comps:NSDateComponents = calendar!.components(NSCalendarUnit.HourCalendarUnit|NSCalendarUnit.MinuteCalendarUnit|NSCalendarUnit.SecondCalendarUnit,fromDate: now)
        comps.calendar = calendar;
        comps.day = 3;
        comps.hour = 8;
        
        let now2 = comps.date;
        println(now2);// -> Optional(0001-01-02 22:49:43 +0000) 日本時間なので+9時間。
        
        var notification = UILocalNotification()
        notification.alertBody = "hogehoge"
        notification.timeZone = NSTimeZone.defaultTimeZone();
        notification.fireDate = now2;
        notification.repeatInterval = NSCalendarUnit.CalendarUnitMonth;
        UIApplication.sharedApplication().scheduleLocalNotification(notification)

Notificationを受け取る(アプリが非アクティブの場合)

アプリがバックグランドで起動している場合は以下の関数で受け取ります。


func application(application: UIApplication, handleActionWithIdentifier identifier: String?, forLocalNotification notification: UILocalNotification, completionHandler: () -> Void) {
     var alert = UIAlertView();
     alert.title = "非アクティブなのに受け取りました";
     alert.message = notification.alertBody;
     alert.addButtonWithTitle(notification.alertAction!);
     alert.show();
}

Notificationを受け取る(アプリが起動していない場合)

アプリが起動していない場合は起動時にはAppDelegate.swiftのいつものapplication:didFinishLaunchingWithOptionsが呼ばれます。 その際のオプションにLocalNotificationを経由しての起動かどうかを判別できますので、その方法で対応します。


    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary!) -> Bool {
        // Override point for customization after application launch.
        
       //実行アプションがあるかどうか
        if let option = launchOptions {
            
            let notification = launchOptions?[UIApplicationLaunchOptionsLocalNotificationKey] as UILocalNotification!
            if (notification != nil) {
                //notificationを実行します
                var alert = UIAlertView();
                alert.title = "LocalNotification経由で起動しました";
                alert.show();
                
                //キャンセルしないと残ってしまいますのでキャンセルします
                UIApplication.sharedApplication().cancelLocalNotification(notification);
            }
          
        return true
    }

※2015/03/20 XCode6.3で動作しませんでしたので修正しました。

Notificationを受け取る(アプリが起動していない場合 + useInfoが含まれる場合)

アプリが起動していない場合は起動時のNotifcatoinにuserInfoが含まれている場合のサンプルがなかったので追記しました。

UILocalNotificationの場合


        var notification = UILocalNotification()
        notification.fireDate = NSDate(timeIntervalSinceNow: 15);//5秒後
        notification.timeZone = NSTimeZone.defaultTimeZone()
        notification.alertBody = "swift-saralymanからの通知だよ"
        notification.alertAction = "OK"
        notification.soundName = UILocalNotificationDefaultSoundName
        notification.userInfo = ["url":"http://swift-salaryman.com"];
        

例えば、上記のようにuserInfoがセットされている場合、どうやって抜き取るかを説明します。


     if let option = launchOptions {
        
        let notification = launchOptions?[UIApplicationLaunchOptionsLocalNotificationKey] as UILocalNotification!
        if (notification != nil) {
            if let userInfo = notification.userInfo{
                
                if let url = userInfo["url"] as String!{
                    var alert = UIAlertView();
                    alert.title = url;
                    alert.show();
                }
            }
            
            //キャンセルしないと残ってしまいますのでキャンセルします
            UIApplication.sharedApplication().cancelLocalNotification(notification);
        }
        
    }

RemoteNotificationの場合


 if let option = launchOptions {
            let userInfo = launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey] as NSDictionary!
            if (userInfo != nil){
                if let url = userInfo["url"] as String!{
                    var alert = UIAlertView();
                    alert.title = url;
                    alert.show();
                }
            }
        }
 

userInfoの扱いが若干UILocalNotificationと違うので注意です。この箇所でNSUserDefaultなんかに値をいれてViewControllerでチェックする 等の処理をいれれば通常起動との分岐処理を行います。

haven't received permission from the user to display alertsのエラー

iOS8以降だとLocalnotificationの初期化が必要なので、AppDelegateに以下を追加する必要があります。 これが正常に実行されると、通知を許可しますか?のダイアログが表示されます。



 func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject : AnyObject]?) -> Bool {
        application.registerUserNotificationSettings(UIUserNotificationSettings(forTypes: UIUserNotificationType.Sound | UIUserNotificationType.Alert | UIUserNotificationType.Badge, categories: nil))
        return true
    }

毎日同じ時間に起動する通知を作成する関数を作成しました。

毎日同じ時間に実行する通知のサンプルを以下記載しておきます。notification.repeatIntervalを調整すれば 毎月だったり毎年だったりを調整できます。


    // self.setEveryDayNotification(8,minute: 5,message: "おはようございます!");//8時5分に毎日実行されます。
    func setEveryDayNotification(hour:Int,minute:Int,message:String){
        
        let now = NSDate()
        let calendar = NSCalendar(identifier: NSCalendarIdentifierGregorian)
        var comps:NSDateComponents = calendar!.components(NSCalendarUnit.MinuteCalendarUnit|NSCalendarUnit.HourCalendarUnit|NSCalendarUnit.MinuteCalendarUnit|NSCalendarUnit.SecondCalendarUnit,fromDate: now)
        comps.calendar = calendar;
        comps.hour = hour;
        comps.minute = minute;
        
        var notification = UILocalNotification()
        notification.alertBody = message;
        notification.timeZone = NSTimeZone.defaultTimeZone();
        notification.fireDate = comps.date;
        notification.repeatInterval = NSCalendarUnit.CalendarUnitDay;//毎日
        UIApplication.sharedApplication().scheduleLocalNotification(notification)
    }

まとめ

どんどん仕様が変わるので大変です!あとシュミレータのアプリを終了させる方法がわからなかったのですが、 シフト+コマンド+Hx2で終了できるようでした。知りませんでしたが、Notificationのlaunchoptionを調査するには 便利ですので使ってみてください!

↓こんな記事もありますよ!

Backslashを忘れない

ショートカットキーで(\)を入力するには「optionキーを押しながら、¥キーを押す」で可能なのですが、 なにかと、あれ、、、なんだったっけ?と忘れる事が多かったので、バックスラッシュ拡大表示。

UIPageControlでペラペラめくるチュートリアル画面を作成する

UIPageControllでiOSアプリ初回起動時にのみ表示される, ペラペラめくるチュートリアル機能の説明です。プロジェクト作成時にPage-Basedを選ぶと作成することはできるのですが、既存のアプリに追加するには気がので、 既に作成したアプリに初回一回だけ表示するチュートリアルを解説します

WatchKitでタイマーアプリを作成する。

簡単なアプリを作成しながらAppleWatchを学んでいきます。前回の記事で大まかな動きは理解できましたので、 つぎはAppleWatchとアプリとの連携をタイマー機能を利用して検証していきます
このエントリーをはてなブックマークに追加
右側のFacebookのLikeをクリック頂けると記事更新の際に通知されますので宜しければご利用下さい!