ROADTO みちログ

ひとのみちのブログ。大阪でiOSアプリの道を歩くフリーランス。

WWDC2016セッションメモ「Advanced Notifications」

WWDC2016セッションを見たメモです。
文中の画像やコードは公開情報から引用しています。
正確で詳しい内容をお求めの方は一次情報の確認をおすすめします。

Advanced Notifications

Advanced Notifications - WWDC 2016 - Videos - Apple Developer

Media Attachments

ペイロード

{ 
    aps: { 
        alert: { ... }, 
        mutable-content: 1 
    } 
    my-attachment: "https://example.com/photo.jpg" 
} 

f:id:hitonomichi:20160624104746p:plain

// Adding an attachment to a user notification
public class NotificationService: UNNotificationServiceExtension {
    override public func didReceive(_ request: UNNotificationRequest,
                                      
                                      
                                      withContentHandler contentHandler: (UNNotificationContent) -> Void) {
        let fileURL = // ...
        let attachment = UNNotificationAttachment(identifier: "image",
                                                  url: fileURL,
                                                  options: nil)
        let content = request.content.mutableCopy as! UNMutableNotificationContent 
        content.attachments = [ attachment ]
        contentHandler(content)
    }
}

Media Attachments は、
Local notifications も Remote notifications も対応。
対応してるのは画像、音声、ビデオ。
時間やサイズに制限はあるよ。

Custom User Interface

通知内容を拡張できる。
ビューをカスタムできる。
通知アクションに応答する。

Notification Content Extension

「Notification Content」を選択。
f:id:hitonomichi:20160624104749p:plain

UNNotificationContentExtension を継承したUIViewControllerのサブクラスができる。

カスタムビュー

class NotificationViewController: UIViewController, UNNotificationContentExtension {

    @IBOutlet var eventTitle: UILabel!
    @IBOutlet var eventDate: UILabel!
    @IBOutlet var eventLocation: UILabel!
    @IBOutlet var eventMessage: UILabel!
    func didReceive(_ notification: UNNotification) {
        let content = notification.request.content
        eventTitle.text = content.title
        eventDate.text = content.subtitle
        eventMessage.text = content.body
        
        if let location = content.userInfo["location"] as? String {
            eventLocation.text = location
        }
    }
}

eventMessageの箇所
f:id:hitonomichi:20160624104751p:plain

eventMessageの箇所
f:id:hitonomichi:20160624104753p:plain

plistにいろいろ設定するらしい。 f:id:hitonomichi:20160624104755p:plain
f:id:hitonomichi:20160624104756p:plain
 こうなる。
f:id:hitonomichi:20160624104758p:plain
The Bash〜のところがUNNotificationExtensionInitialContentSizeRatioで措定されている。
Default content が非表示になってる。

メディアの追加

設定する。

// Notification Content Extension Attachments
class NotificationViewController: UIViewController, UNNotificationContentExtension {
    @IBOutlet var eventImage: UIImageView!
    func didReceive(_ notification: UNNotification) {
        let content = notification.request.content
        if let attachment = content.attachments.first {
            if attachment.url.startAccessingSecurityScopedResource() {
                eventImage.image = UIImage(contentsOfFile: attachment.url.path!)
                attachment.url.stopAccessingSecurityScopedResource()
            }
        }
    }
}

こうなる。
f:id:hitonomichi:20160624104804p:plain

アクションとレスポンス

// Intercepting notification action response
class NotificationViewController: UIViewController, UNNotificationContentExtension {
    func didReceive(_ response: UNNotificationResponse,
                      completionHandler done: (UNNotificationContentExtensionResponseOption) -> Void) {
        server.postEventResponse(response.actionIdentifier) {
            if response.actionIdentifier == "accept" {
                eventResponse.text = "Going!"
                eventResponse.textColor = UIColor.green()
            } else if response.actionIdentifier == "decline" {
                eventResponse.text = "Not going :("
                eventResponse.textColor = UIColor.red()
            }
            
            // done(.dismiss)
            done(.dismissAndForwardAction) 
        }

        }
    }
}

こうなる。
f:id:hitonomichi:20160624104806p:plain

テキスト入力

UNNotificationCategoryをつくる。

// Text Input Action
private func makeEventExtensionCategory() -> UNNotificationCategory {
    let commentAction = UNTextInputNotificationAction(
        identifier: "comment",
        title: "Comment",
        options: [],
        textInputButtonTitle: "Send",
        textInputPlaceholder: "Type here...")
    return UNNotificationCategory(identifier: "event-invite",
                                  actions: [ acceptAction, declineAction, commentAction ],
}

こうなる。
f:id:hitonomichi:20160624104809p:plain

// Text input action response
class NotificationViewController: UIViewController, UNNotificationContentExtension {
    func didReceive(_ response: UNNotificationResponse,
                      completionHandler done: (UNNotificationContentExtensionResponseOption) -> Void) {
        if let textResponse = response as? UNTextInputNotificationResponse {
            server.send(textResponse.userText) {
                done(.dismiss)
            }
        }
    }
}

アクセサリーのカスタム(?)

// Custom input accessory view
class NotificationViewController: UIViewController, UNNotificationContentExtension {
    override func canBecomeFirstResponder() -> Bool {
        return true
    }
    override var inputAccessoryView: UIView { get {
        return inputView
        }
    }
    func didReceive(_ response: UNNotificationResponse,
                      completionHandler done: (UNNotificationContentExtensionResponseOption) -> Void) {
    }
}

感想

出来ることが増えてここだけで機能完結できることもありそう。 がんばってリッチな通知するぞー!

WWDC2016セッションメモシリーズはこちら

WWDC2016 カテゴリーの記事一覧 - ROADTO みちログ

自己紹介
メガネは売っていません
高浜 一道(たかはま かずみち)
大阪でiOSアプリの道を歩くフリーランス。
iPad・iPhoneとサーバを連携した、JSONやDBといったキーワードが出てくるツール系が多めです。
お仕事のご依頼やご連絡はこちらから。
お仕事ください!
Web : ROADTO
ML : k-takahama(a)roadto.jp

個人的なアカウントはこちら。
Tw : @hitonomichi
Fb : kazumichi.takahama