LoginSignup
2
2

More than 5 years have passed since last update.

UNNotificationContentExtension で 画像をダウンロードしたり、AppGroupでアプリ本体と情報共有したり

Last updated at Posted at 2017-09-21

httpで通信してて工数殺したので自戒の念を込めて書いてたんですが、
Extensionで画像をダウンロードしてーってQiita無いなって思ったのでそれも含めて書いてます。
なお、今更HTTPを使うなというのがAppleの意向なのでそれに従う必要があります。1

あと、AppGroupsをこのExtensionで使ったってQiitaもないのでTIPSにいれておきました。

httpsを使わないと

UNErrorDomainが Throw されます。

前提

  • 既に UNNotificationContentExtension を使ったものが実装されてる

実装

  • 画像ファイルは存在している.サーバー側に問題は無い。
  • Extensionじゃない本体では、 App Transport Security Settings を設定している
    • 本体側ではhttp通信をしている箇所がある
  • import UserNotifications import UIKit だけ使いたい。
  • 画像(png/jpg)をダウンロードするコードは以下
myNotificationExtension.swift
import UserNotifications
import UIKit

class NotificationService: UNNotificationServiceExtension {
    var contentHandler: ((UNNotificationContent) -> Void)?
    var bestAttemptContent = UNMutableNotificationContent.init()

    // ...
    // 割愛
    // ...


    override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
      self.contentHandler = contentHandler
      bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)!
      let host = "https://abcdefg-hogetarou.tv" // httpだと出来ない!!!
      let image = "/terebibangumi.png"
      let fileManager = FileManager.default
      let tmpSubFolderName = ProcessInfo.processInfo.globallyUniqueString
      let tmpSubFolderURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(tmpSubFolderName, isDirectory: true)
      let session = URLSession(configuration: URLSessionConfiguration.default)
      let task = session.dataTask(with: URL(string: host + image)!, completionHandler: { (data, response, error) in
          do {
              self.bestAttemptContent.title = "\(self.bestAttemptContent.title)"
              try fileManager.createDirectory(at: tmpSubFolderURL, withIntermediateDirectories: true, attributes: nil)
              let imageFileIdentifier = "banbumi.png"
              let fileURL = tmpSubFolderURL.appendingPathComponent(imageFileIdentifier)
              try data?.write(to: fileURL)
              let imageAttachment = try UNNotificationAttachment.init(identifier: imageFileIdentifier, url: fileURL, options: nil)
              self.bestAttemptContent.attachments = [imageAttachment]
          } catch let e {
              self.bestAttemptContent.body = "\(String.init(describing: e))"
          }
          contentHandler(self.bestAttemptContent)
      })
      task.resume() 
      // ....
      // 割愛
      // ....

☝️ 色んな者を do で囲むのは Exception 投げられたときに追いづらくなる可能性があるので、上記のようにせずきちんと分けることをオススメします。

TIPS

  • エラーの時にタイトルを変えられるが、ユーザーにエラーがおこってるな?と思われてはいけない(と思うので)タイトルの最後に . とか , とか付けてデバッグデバッグ出来るようにしてる。
    • 上記では、 eをそのままbodyにいれている。これは開発用なので参考にする人がいれば注意.
  • 画像がhttp通信が原因で、Exceptionが投げられると UNErrorDomainInvalid attachment file URL みたいなのが届く。HTTPSを使えば解消できる。

アプリ本体と情報共有

AppGroupsを使えば、アプリ本体から情報をもらうことができる。

 1. Developer Center で App Groups を定義

AppGroup.png

2. Xcodeで機能を有効にして、AppGroupを追加する

Xcode.png

3. 実装する

取得する方法:

myNotificationExtension.swift
let groupName = "group.terebi.dayo"
if let userDefaults = UserDefaults(suiteName: groupName) {
    let key = "video_killed_the radio_star"
    userDefaults.synchronize() //念のため
    let savedCount = userDefaults.integer(forKey: key) // 取れる yay
    // 割愛

設定する方法:

Interactor.swift
let groupName = "group.terebi.dayo"
if let userDefaults = UserDefaults(suiteName: groupName) {
    let key = "video_killed_the radio_star"
    userDefaults.set(0, forKey: key) // 設定できる yay
    userDefaults.synchronize() //念のため
}

最後に

3ヶ月前にも同じ事をやってこの現象の原因は知っていたが、今回も1日掛かってしまった。
ちなみに前回は3日間かかった。
自戒の念を込めてTIPSを残す。


  1. ATS使えば通信できるかも??かも??でも明日には使え無くなる可能性有るかも?? 

2
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2