iOS8での通知関連の変更について, WWDC2014, また以後公開されているリファレンスによる情報をまとめた.
iOS8から変わる点はおおきくわけると以下の3つになる.
- UIUserNotificationの登場
- 登録/通知取得方法の変更
- CoreLocationを使った通知
以下, サンプルコードを示しながら説明していく.
端的にいうと新たに以下の3つのクラスが追加された. (これらのMutableなクラスも存在する)
- UIUserNotificationAction
- UIUserNotificationCategory
- UIUserNotificationSettings
- 通知は, バナー, 通知センター, アラートなどいくつかの表現がある.
- しかし, 通知をタップ, スワイプしたときの挙動は限定的だった. (アプリがフォアグラウンドにくる)
- User Notification クラス群は通知に対してインタラクティヴな挙動をユーザに提供するためのクラス群.
// 画像
これによって例えばメールを受信した通知をスワイプして返信ボタンを出現させるなどができるようになる.
- 通知時に実行するボタンに対応するアクションを定義する.
- 実際の処理に関しては知らない.
以下の様な感じでプロパティをセットする.
UIMutableUserNotificationAction *acceptAction = [[UIMutableUserNotificationAction alloc] init];
acceptAction.identifier = @"ACCEPT_IDENTIFIER"; // Delegate時に渡されるID
acceptAction.title = @"Accept"; // ボタンのタイトル
acceptAction.activationMode = UIUserNotificationActivationModeBackground;
acceptAction.destructive = NO;
acceptAction.authenticationRequired = NO;
activationMode
はバックグラウンド起動するかフォアグラウンド起動するかを設定する.- UIを表示する必要があればForeGroundとかんがえる.
destructive
は破壊的な実行を伴うか否か. YESだと赤色になる.authenticationRequired
はデバイスがロック時にパスコードを求めるか否か.- これがYESでかつ, backgroundだとアンロックされないので注意.
参考までにWWDCのセッションでのデモでは,
- 招待の承諾はUIがいらないのでbackground, destructiveはNO, 無害なので認証不要.
- ゴミ箱へ捨てるはUIがいらないのでbackground, destructiveはYES, 捨てられると嫌なので認証必要(?)
- 返信ボタンはUIが必要なのでForeground, destructiveはNO, 認証は必要と考えるのが妥当だが, Foregroundなのでいずれにせよ入力が必要.
- (この設定は効果をもたない)
という感じだった.
- Actionは通常一種類の通知に対して複数関連付けられる.
UIUserNotificationCategory
は複数のアクションをカテゴライズする.
UIMutableUserNotificationCategory *inviteCategory = [UIMutableUserNotificationCategory new];
inviteCategory.identifier = @"INVITE_CATEGORY"; // このIDを通知する側からも設定する
[inviteCategory setActions:@[acceptAction, maybeAction, declineAction] forContext:UIUserNotificationActionContextDefault];
UIUserNotificationActionContext
はアクションを表示する際のコンテクストでDefault, minimumの二種類.- Defaultの場合は4つまでActionを表示できる. Minimumの場合は2つまでしか表示できない.
- DefaultとMinimalでそれぞれ
setAction:
できる. そうするとアラート時は4つ, ほかは2つとかにできる.
- 通知のタイプやアクションのカテゴリなどの設定情報をもつ.
- この設定をあらかじめ登録しておくことで, 通知を受けることができる.
registerUserNotificationSettings:
で登録するとユーザの許可を求める.
NSSet *categories = [NSSet setWithObjects:inviteCategory, nil];
UIUserNotificationType types = (UIUserNotificationTypeBadge |
UIUserNotificationTypeSound |
UIUserNotificationTypeAlert);
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:types categories:categories];
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
許可が降りるとapplication:didRegisterUserNotificationSettings:
が呼ばれる.
- (void)application:(UIApplication *)application
didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{
// user has allowed receiving user notifications of the following types
UIUserNotificationType allowedTypes = [notificationSettings types];
}
現在の設定情報を取得するには, currentUserNotificationSettings
を使う.
enabledRemoteNotificationTypes
はdeprecatedになった.
UserNotificationsの導入により, 通知の登録やそのDelegate, 通知時に呼び出されるDelegateも変更/追加があった.
~iOS6とiOS7で微妙に異なるがおよそ以下のようになっている.
- 初回起動の場合は
application:didFinishLaunchingWithOptions:
が呼ばれる. - それ以外は
application:didReceiveRemoteNotification:fetchCompletionHandler:
が呼ばれる.- (iOS6以前は
application:didReceiveRemoteNotification:
)
- (iOS6以前は
くわしくは以下によくまとめられている.
- カテゴリIDをpayloadに含める.
- payloadのサイズが2KBに増えた.
{ "aps" : { "alert" : "You're invited!", "category" : "INVITE_CATEGORY" } }
UILocalNotification
のプロパティに新しくcategory
が追加されたのでセットする.
iOS8では
application:handleActionWithIdentifier:forLocalNotification:completionHandler:
application:handleActionWithIdentifier:forRemoteNotification:completionHandler:
の2つだけでOK. (旧APIだと届くのか未検証)
例としては以下のようになる.
- (void)application:(UIApplication *)application
handleActionWithIdentifier:(NSString *)identifier
forRemoteNotification:(NSDictionary *)userInfo
completionHandler:(void (^)())completionHandler
{
if ([identifier isEqualToString:@"ACCEPT_IDENTIFIER"]) {
// do stuff
}
// Must be called when finished
completionHandler();
}
ここは変更がややこしいので概念的なところを整理.
-
これまでNotificationという概念はRemote/Localという分類のみだった.
-
が, iOS8からは別軸にUserNotification/SilentNotificationというユーザのインタラクションの有無が追加.
-
UIやユーザの承認をえるシーケンスはUserNotificationにまとめられるようになった.
-
そのためRemoteNotificationの登録方法などが分離されている.
-
通知の種類によって別途必要な処理がある.
-
UserNotification, つまりユーザのインタラクションを介する通知(バナーとか通知センターとかいわゆるPush通知)
-
SilentNotification, iOS7以降可能になったバックグラウンド通信のみのサイレント通知
-
UserNotificationの場合は
registerUserNotificationSettings:
を使って通知時にインタラクションを設定する. -
SilentNotificationの場合はinfo.plist でUIBackgroundModesの設定が必要(Remote Notification)
-
インタラクションとの分離によって,
registerForRemoteNotificationTypes
はdeprecatedになった.
[[UIApplication sharedApplication] registerForRemoteNotifications];
delegate側は変わらない.
- ある特定の場所に近づいたことをトリガーに通知できる.
- iOS7以前も実現できたが, シンプルに実装できるようになった.
- UILocalNotificationを使う.
- あくまでも位置情報が有効になっているときに使える.
CoreLocationの処理は省略
UILocalNotification *locNotification = [[UILocalNotification alloc] init];
locNotification.alertBody = @"You have arrived!";
locNotification.regionTriggersOnce = YES;
locNotification.region = [[CLCircularRegion alloc] initWithCenter:LOC_COORDINATE
radius:LOC_RADIUS
identifier:LOC_IDENTIFIER];
[[UIApplication sharedApplication] scheduleLocalNotification:locNotification];