【swift】iOSシェア機能でファイルを受信する実装

概要

Gmail等に添付されているファイルをシェア機能と使って受取る実装です。

開発環境

  1. Mac OS 11.6.2
  2. Xcode 13.1

事前準備

  • Gmail等シェアできるアプリが必要です。

Info.plistの設定

  • TARGETのInfoから設定するとわかりやすいでしょう

直接設定しても反映されます。
f:id:develop-imonari:20220106142539p:plain

  • nameに適当な名前、Typesにファイルタイプを入れます。

ファイルタイプは受取りたいファイルの種別です。System-Declared Uniform Type Identifiersを参照してくださいIdentifier列の値を入れます。
developer.apple.com

  • 例:テキストファイルはpublic.text、画像ファイル(png)はpublic.png等、複数設定することも可能です。
  • またpublic.dataを設定することで全てのTypeを受けることが出来ます。

f:id:develop-imonari:20220106144920p:plain

  • 他のアプリからのシェア機能で現れました。

受信したファイルのURLの取得

  • iOS13からはSceneDelegateで受け取ります。
  • アプリが起動している時
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
    // アプリが起動している場合はこのメソッドで受ける
    // URLContextsにはいているURLが受信したファイルのURL
    let content = urlContexts.first
    let url = content?.url
}
  • アプリが起動していない
var urlContexts: Set<UIOpenURLContext>?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    // アプリが起動していない時は起動時にここでシェアするファイルのURL取得する。
    urlContexts = connectionOptions.urlContexts
    guard (scene as? UIWindowScene) != nil else {
        return
    }
}

【swift】iOSでPush通知に画像表示する実装

開発環境

  1. Mac OS 11.6.2
  2. Xcode 13.1

事前準備

  • Push通知を受け取る実装をしておいてください

develop-imonari.hatenablog.com

TARGETにNotification Service Extensionを追加

f:id:develop-imonari:20211228140929p:plain
f:id:develop-imonari:20211228140944p:plain
f:id:develop-imonari:20211228140956p:plain

f:id:develop-imonari:20211228163400p:plain

NotificationServiceの実装

  • TargetにNotification Service Extensionを追加するとデフォルトでNotificationService.swiftが出来上がります。
  • NotificationService.swiftのdidReceiveに画像ダウンロードと設定を行うことで、受取ったPush通知に画像が表示されます。
  • 取り出す要素名はJSONと同じにしなければならないので後述を参照してください
// プッシュ通知が届いたらこのメソッドにコールバックされます。
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
    self.contentHandler = contentHandler
    bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
    // プッシュ通知のペイロードからUserInfo部分を取り出す
    if let attachment = request.content.userInfo["rpr_attachment"] as? [String: String] {
        // ペイロードに要素があれば取得
        if let urlString = attachment["url"], let fileURL = URL(string: urlString), let type = attachment["type"] {
            // urlはファイルパス。typeは拡張子
            // ペイロードのrpr_attachmentのurlからファイルをダウンロードする
            URLSession.shared.downloadTask(with: fileURL) { (location, response, error) in
                if let location = location {
                    let fileName = UUID().uuidString + "." + type
                    let tmpFile = "file://".appending(NSTemporaryDirectory()).appending(fileName)
                    let tmpUrl = URL(string: tmpFile)!
                    try? FileManager.default.moveItem(at: location, to: tmpUrl)
                    if let attachment = try? UNNotificationAttachment(identifier: "IDENTIFIER", url: tmpUrl, options: nil) {
                        self.bestAttemptContent?.attachments = [attachment]
                    }
                }
                contentHandler(self.bestAttemptContent!)
            }.resume()
        }
    } else {
        contentHandler(self.bestAttemptContent!)
    }
}

Push通知を試す。

  • テストツール(こちらを使ってみました。)

github.com

  • 各種設定値とカスタムJSONを設定してPushボタンで送信です。

最初は時間がかかるので少し待ってください
f:id:develop-imonari:20211228162237p:plain

  • 受取った通知に画像が出ました。

  • 通知を下にドラッグすると画像を大きくすることが出来ます。

【swift】iOSでPush通知を受取る実装

開発環境

  1. Mac OS 11.6.2
  2. Xcode 13.1

事前準備

  • Apple Developer Programの登録

developer.apple.com

  • Push通知に必要な証明書の作り方(丁寧に書かれています。)

qiita.com

Xcodeプロジェクトの設定

  1. プロジェクトには事前準備2で設定したバンドルを設定してください
  2. TARGETの設定で+CapabilityからPush Notificationsを追加してください

f:id:develop-imonari:20211223214944p:plain
f:id:develop-imonari:20211223215007p:plain
f:id:develop-imonari:20211223215147p:plain

AppDelegateの実装

  • func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) にプッシュ通知の利用許可を記載します。
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    // プッシュ通知の利用許可
    UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { granted, error in
        guard granted else { return }
        DispatchQueue.main.async {
            // プッシュ通知の登録
            UIApplication.shared.registerForRemoteNotifications()
        }
    }
    return true
}
  • プッシュ通知の登録が成功した場合のCallBack関数を記述
// プッシュ通知の登録が成功した場合CallBackされる
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    let token = deviceToken.map {
        String(format: "%.2hhx", $0)
    }.joined()
    NSLog("DeviceToken: \(token)")
}
  • プッシュ通知の登録が失敗した場合のCallBack関数を記述
// プッシュ通知の登録が失敗した場合CallBackされる
func application(_ application: UIApplication,  didFailToRegisterForRemoteNotificationsWithError error: Error) {
    NSLog("エラー: \(error)")
}

アプリを実機にインストールしてデバイストークンを取得

  • 実機を接続しアプリをインストールすると許可ダイアログが表示されるので許可する

f:id:develop-imonari:20211223224430p:plain