Contenu connexe
Similaire à New Notification API in iOS 10 (20)
New Notification API in iOS 10
- 2. Copyright © Up-frontier, Inc. All rights reserved.
アジェンダ
• 新 API でローカル通知
• Media Attachment
• Notification Content Extension
• Notification Service Extension
2
- 3. Copyright © Up-frontier, Inc. All rights reserved.
アジェンダ
• 新 API でローカル通知
• Media Attachment
• Notification Content Extension
• Notification Service Extension
3
- 6. Copyright © Up-frontier, Inc. All rights reserved.
コンテンツ
let content = UNMutableNotificationContent()
content.title = "Title"
content.subtitle = "Subtitle"
content.body = "Body"
content.categoryIdentifier = "sample-category"
6
- 7. Copyright © Up-frontier, Inc. All rights reserved.
コンテンツ
let content = UNMutableNotificationContent()
content.title = "Title"
content.subtitle = "Subtitle"
content.body = "Body"
content.categoryIdentifier = "sample-category"
7
- 8. Copyright © Up-frontier, Inc. All rights reserved.
コンテンツ
let content = UNMutableNotificationContent()
content.title = "Title"
content.subtitle = "Subtitle"
content.body = "Body"
content.categoryIdentifier = "sample-category"
8
Action や、カスタム UI など
識別に使⽤
- 11. Copyright © Up-frontier, Inc. All rights reserved.
トリガー
UNNotificationTrigger
11
let intervalTrigger = UNTimeIntervalNotificationTrigger(
timeInterval: 5, repeats: false)
- 12. Copyright © Up-frontier, Inc. All rights reserved.
リクエスト
let id = "sample-(Date().timeIntervalSince1970)"
let request = UNNotificationRequest(
identifier: id,
content: content,
trigger: intervalTrigger
)
center.add(request) { error in
if let error = error {
print("Error on requesting notification: (error)")
}
print("Finish requesting notification: (id)")
}
12
- 13. Copyright © Up-frontier, Inc. All rights reserved.
リクエスト
let id = "sample-(Date().timeIntervalSince1970)"
let request = UNNotificationRequest(
identifier: id,
content: content,
trigger: intervalTrigger
)
center.add(request) { error in
if let error = error {
print("Error on requesting notification: (error)")
}
print("Finish requesting notification: (id)")
}
13
トリガのセット
- 14. Copyright © Up-frontier, Inc. All rights reserved.
リクエスト
let id = "sample-(Date().timeIntervalSince1970)"
let request = UNNotificationRequest(
identifier: id,
content: content,
trigger: intervalTrigger
)
center.add(request) { error in
if let error = error {
print("Error on requesting notification: (error)")
}
print("Finish requesting notification: (id)")
}
14
identifier: 識別⼦、更新・削除に利⽤
contents: 通知本体
trigger: 発⽕タイミング
- 15. Copyright © Up-frontier, Inc. All rights reserved.
リクエスト
let id = "sample-(Date().timeIntervalSince1970)"
let request = UNNotificationRequest(
identifier: id,
content: content,
trigger: intervalTrigger
)
center.add(request) { error in
if let error = error {
print("Error on requesting notification: (error)")
}
print("Finish requesting notification: (id)")
}
15
Notification Centerに追加で完了
- 16. Copyright © Up-frontier, Inc. All rights reserved.
アジェンダ
• 新 API でローカル通知
• Media Attachment
• Notification Content Extension
• Notification Service Extension
16
- 22. Copyright © Up-frontier, Inc. All rights reserved.
UNNotificationAttachment
guard let imageURL = R.file.sampleJpg() else {
print("Could not instantiate file URL!”)
return
}
let content = defaultContent
do {
let attachment = try UNNotificationAttachment(
identifier: "sample-cat",
url: imageURL,
options: nil
)
content.attachments = [attachment]
} catch(let error) {
print("Could not instantiate attachment: (error)")
}
22
- 23. Copyright © Up-frontier, Inc. All rights reserved.
UNNotificationAttachment
guard let imageURL = R.file.sampleJpg() else {
print("Could not instantiate file URL!”)
return
}
let content = defaultContent
do {
let attachment = try UNNotificationAttachment(
identifier: "sample-cat",
url: imageURL,
options: nil
)
content.attachments = [attachment]
} catch(let error) {
print("Could not instantiate attachment: (error)")
}
23
画像の設定
UNNotificationAttachmentを使う
- 24. Copyright © Up-frontier, Inc. All rights reserved.
UNNotificationAttachment
guard let imageURL = R.file.sampleJpg() else {
print("Could not instantiate file URL!”)
return
}
let content = defaultContent
do {
let attachment = try UNNotificationAttachment(
identifier: "sample-cat",
url: imageURL,
options: nil
)
content.attachments = [attachment]
} catch(let error) {
print("Could not instantiate attachment: (error)")
}
24
コンテンツに指定
- 25. Copyright © Up-frontier, Inc. All rights reserved.
アジェンダ
• 新 API でローカル通知
• Media Attachment
• Notification Content Extension
• Notification Service Extension
25
- 29. Copyright © Up-frontier, Inc. All rights reserved.
NotificationViewController
class NotificationViewController
: UIViewController
, UNNotificationContentExtension {
@IBOutlet weak var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
}
func didReceive(_ notification: UNNotification) {
let content = notification.request.content
if
let lat = content.userInfo["latitude"] as? Double,
let lon = content.userInfo["longitude"] as? Double
{
putPin(into: CLLocationCoordinate2D(latitude: lat, longitude:
lon))
}
}
}
29
- 30. Copyright © Up-frontier, Inc. All rights reserved.
NotificationViewController
class NotificationViewController
: UIViewController
, UNNotificationContentExtension {
@IBOutlet weak var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
}
func didReceive(_ notification: UNNotification) {
let content = notification.request.content
if
let lat = content.userInfo["latitude"] as? Double,
let lon = content.userInfo["longitude"] as? Double
{
putPin(into: CLLocationCoordinate2D(latitude: lat, longitude:
lon))
}
}
}
30
MapViewを持った通知
- 31. Copyright © Up-frontier, Inc. All rights reserved.
NotificationViewController
class NotificationViewController
: UIViewController
, UNNotificationContentExtension {
@IBOutlet weak var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
}
func didReceive(_ notification: UNNotification) {
let content = notification.request.content
if
let lat = content.userInfo["latitude"] as? Double,
let lon = content.userInfo["longitude"] as? Double
{
putPin(into: CLLocationCoordinate2D(latitude: lat, longitude:
lon))
}
}
}
31
通知が発⽕した時の処理
- 32. Copyright © Up-frontier, Inc. All rights reserved.
NotificationViewController
class NotificationViewController
: UIViewController
, UNNotificationContentExtension {
@IBOutlet weak var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
}
func didReceive(_ notification: UNNotification) {
let content = notification.request.content
if
let lat = content.userInfo["latitude"] as? Double,
let lon = content.userInfo["longitude"] as? Double
{
putPin(into: CLLocationCoordinate2D(latitude: lat, longitude:
lon))
}
}
}
32
通知が発⽕した時の処理
通知内容を反映
- 33. Copyright © Up-frontier, Inc. All rights reserved.
Info.plist
<dict>
<key>NSExtensionAttributes</key>
<dict>
<key>UNNotificationExtensionCategory</key>
<array>
<string>customUI</string>
</array>
<key>UNNotificationExtensionInitialContentSizeRatio</key>
<real>1</real>
<key>UNNotificationExtensionDefaultContentHidden</key>
<true/>
</dict>
<key>NSExtensionMainStoryboard</key>
<string>MainInterface</string>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.usernotifications.content-extension</
string>
</dict> 33
- 34. Copyright © Up-frontier, Inc. All rights reserved.
Info.plist
<dict>
<key>NSExtensionAttributes</key>
<dict>
<key>UNNotificationExtensionCategory</key>
<array>
<string>customUI</string>
</array>
<key>UNNotificationExtensionInitialContentSizeRatio</key>
<real>1</real>
<key>UNNotificationExtensionDefaultContentHidden</key>
<true/>
</dict>
<key>NSExtensionMainStoryboard</key>
<string>MainInterface</string>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.usernotifications.content-extension</
string>
</dict> 34
categoryIdentifierと
⼀致している必要あり
- 35. Copyright © Up-frontier, Inc. All rights reserved.
Info.plist
<dict>
<key>NSExtensionAttributes</key>
<dict>
<key>UNNotificationExtensionCategory</key>
<array>
<string>customUI</string>
</array>
<key>UNNotificationExtensionInitialContentSizeRatio</key>
<real>1</real>
<key>UNNotificationExtensionDefaultContentHidden</key>
<true/>
</dict>
<key>NSExtensionMainStoryboard</key>
<string>MainInterface</string>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.usernotifications.content-extension</
string>
</dict> 35
UIの縦横⽐
- 36. Copyright © Up-frontier, Inc. All rights reserved.
Info.plist
<dict>
<key>NSExtensionAttributes</key>
<dict>
<key>UNNotificationExtensionCategory</key>
<array>
<string>customUI</string>
</array>
<key>UNNotificationExtensionInitialContentSizeRatio</key>
<real>1</real>
<key>UNNotificationExtensionDefaultContentHidden</key>
<true/>
</dict>
<key>NSExtensionMainStoryboard</key>
<string>MainInterface</string>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.usernotifications.content-extension</
string>
</dict> 36
デフォルトのタイトル、サブタイ
トル、コンテンツ
- 37. Copyright © Up-frontier, Inc. All rights reserved.
アジェンダ
• 新 API でローカル通知
• Media Attachment
• Notification Content Extension
• Notification Service Extension
37
- 40. Copyright © Up-frontier, Inc. All rights reserved.
NotificationService
class NotificationService: UNNotificationServiceExtension {
var contentHandler: ((UNNotificationContent) -> Void)?
var bestAttemptContent: UNMutableNotificationContent?
override func didReceive(_ request: UNNotificationRequest,
withContentHandler contentHandler:
@escaping (UNNotificationContent) -> Void) {
self.contentHandler = contentHandler
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
if let bestAttemptContent = bestAttemptContent {
// Modify the notification content here...
bestAttemptContent.title = "(bestAttemptContent.title) [modified]"
contentHandler(bestAttemptContent)
}
}
override func serviceExtensionTimeWillExpire() {
// Called just before the extension will be terminated by the system.
// Use this as an opportunity to deliver your "best attempt" at modified content,
// otherwise the original push payload will be used.
if
let contentHandler = contentHandler,
let bestAttemptContent = bestAttemptContent {
bestAttemptContent.title = "(bestAttemptContent.title) [Time Expired]"
contentHandler(bestAttemptContent)
}
}
}
40
- 41. Copyright © Up-frontier, Inc. All rights reserved.
NotificationService
class NotificationService: UNNotificationServiceExtension {
var contentHandler: ((UNNotificationContent) -> Void)?
var bestAttemptContent: UNMutableNotificationContent?
override func didReceive(_ request: UNNotificationRequest,
withContentHandler contentHandler:
@escaping (UNNotificationContent) -> Void) {
self.contentHandler = contentHandler
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
if let bestAttemptContent = bestAttemptContent {
// Modify the notification content here...
bestAttemptContent.title = "(bestAttemptContent.title) [modified]"
contentHandler(bestAttemptContent)
}
}
override func serviceExtensionTimeWillExpire() {
// Called just before the extension will be terminated by the system.
// Use this as an opportunity to deliver your "best attempt" at modified content,
// otherwise the original push payload will be used.
if
let contentHandler = contentHandler,
let bestAttemptContent = bestAttemptContent {
bestAttemptContent.title = "(bestAttemptContent.title) [Time Expired]"
contentHandler(bestAttemptContent)
}
}
}
41
通知内容を編集
- 42. Copyright © Up-frontier, Inc. All rights reserved.
NotificationService
class NotificationService: UNNotificationServiceExtension {
var contentHandler: ((UNNotificationContent) -> Void)?
var bestAttemptContent: UNMutableNotificationContent?
override func didReceive(_ request: UNNotificationRequest,
withContentHandler contentHandler:
@escaping (UNNotificationContent) -> Void) {
self.contentHandler = contentHandler
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
if let bestAttemptContent = bestAttemptContent {
// Modify the notification content here...
bestAttemptContent.title = "(bestAttemptContent.title) [modified]"
contentHandler(bestAttemptContent)
}
}
override func serviceExtensionTimeWillExpire() {
// Called just before the extension will be terminated by the system.
// Use this as an opportunity to deliver your "best attempt" at modified content,
// otherwise the original push payload will be used.
if
let contentHandler = contentHandler,
let bestAttemptContent = bestAttemptContent {
bestAttemptContent.title = "(bestAttemptContent.title) [Time Expired]"
contentHandler(bestAttemptContent)
}
}
}
42
処理が既定秒数(MAX30秒)を超えると呼ばれる
- 43. Copyright © Up-frontier, Inc. All rights reserved.
NotificationService
class NotificationService: UNNotificationServiceExtension {
var contentHandler: ((UNNotificationContent) -> Void)?
var bestAttemptContent: UNMutableNotificationContent?
override func didReceive(_ request: UNNotificationRequest,
withContentHandler contentHandler:
@escaping (UNNotificationContent) -> Void) {
self.contentHandler = contentHandler
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
if let bestAttemptContent = bestAttemptContent {
// Modify the notification content here...
bestAttemptContent.title = "(bestAttemptContent.title) [modified]"
contentHandler(bestAttemptContent)
}
}
override func serviceExtensionTimeWillExpire() {
// Called just before the extension will be terminated by the system.
// Use this as an opportunity to deliver your "best attempt" at modified content,
// otherwise the original push payload will be used.
if
let contentHandler = contentHandler,
let bestAttemptContent = bestAttemptContent {
bestAttemptContent.title = "(bestAttemptContent.title) [Time Expired]"
contentHandler(bestAttemptContent)
}
}
}
43
サーバからのリモートプッシュを変更する場合
mutable-contetの設定忘れないように
- 44. Copyright © Up-frontier, Inc. All rights reserved.
NotificationService
class NotificationService: UNNotificationServiceExtension {
var contentHandler: ((UNNotificationContent) -> Void)?
var bestAttemptContent: UNMutableNotificationContent?
override func didReceive(_ request: UNNotificationRequest,
withContentHandler contentHandler:
@escaping (UNNotificationContent) -> Void) {
self.contentHandler = contentHandler
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
if let bestAttemptContent = bestAttemptContent {
// Modify the notification content here...
bestAttemptContent.title = "(bestAttemptContent.title) [modified]"
contentHandler(bestAttemptContent)
}
}
override func serviceExtensionTimeWillExpire() {
// Called just before the extension will be terminated by the system.
// Use this as an opportunity to deliver your "best attempt" at modified content,
// otherwise the original push payload will be used.
if
let contentHandler = contentHandler,
let bestAttemptContent = bestAttemptContent {
bestAttemptContent.title = "(bestAttemptContent.title) [Time Expired]"
contentHandler(bestAttemptContent)
}
}
}
44
処理が終わったら速やかに呼ぶ
- 45. Copyright © Up-frontier, Inc. All rights reserved.
ありそうな使い⽅
• ペイロードにサーバにあるメディアの URL
• ダウンロードして
• Media Attachment
45
- 46. Copyright © Up-frontier, Inc. All rights reserved.
リモートコンテンツ
貼り付け
if let bestAttemptContent = bestAttemptContent {
guard
let urlString = bestAttemptContent.userInfo["remote-url"] as? String,
let remoteURL = URL(string: urlString)
else {
contentHandler(bestAttemptContent)
return
}
download(remoteURL) { url, error in
guard let fileURL = url else {
print(error)
contentHandler(bestAttemptContent)
return
}
do {
let attachment = try UNNotificationAttachment(
identifier: "remote", url: fileURL
)
bestAttemptContent.attachments = [attachment]
contentHandler(bestAttemptContent)
} catch(let e) {
print(e)
contentHandler(bestAttemptContent)
}
}
}
46
- 47. Copyright © Up-frontier, Inc. All rights reserved.
リモートコンテンツ
貼り付け
if let bestAttemptContent = bestAttemptContent {
guard
let urlString = bestAttemptContent.userInfo["remote-url"] as? String,
let remoteURL = URL(string: urlString)
else {
contentHandler(bestAttemptContent)
return
}
download(remoteURL) { url, error in
guard let fileURL = url else {
print(error)
contentHandler(bestAttemptContent)
return
}
do {
let attachment = try UNNotificationAttachment(
identifier: "remote", url: fileURL
)
bestAttemptContent.attachments = [attachment]
contentHandler(bestAttemptContent)
} catch(let e) {
print(e)
contentHandler(bestAttemptContent)
}
}
}
47
画像のダウンロード
30秒超えるかも
- 48. Copyright © Up-frontier, Inc. All rights reserved.
serviceExtensionTimeWillExpire
override func serviceExtensionTimeWillExpire() {
if
let contentHandler = contentHandler,
let bestAttemptContent = bestAttemptContent
{
bestAttemptContent.title += " [頑張ったけれどダメだっ
たよ]"
contentHandler(bestAttemptContent)
}
}
48
- 49. Copyright © Up-frontier, Inc. All rights reserved.
serviceExtensionTimeWillExpire
override func serviceExtensionTimeWillExpire() {
if
let contentHandler = contentHandler,
let bestAttemptContent = bestAttemptContent
{
bestAttemptContent.title += " [頑張ったけれどダメだっ
たよ]"
contentHandler(bestAttemptContent)
}
}
49
サーバからのリモートプッシュの内容を
変更しない場合
もとのペイロードのまま表⽰されてしまうので注意
- 50. Copyright © Up-frontier, Inc. All rights reserved.
まとめ
• 新 API でローカル通知
• Media Attachment
• Notification Content Extension
• Notification Service Extension
50