web-dev-qa-db-ja.com

拡張機能を含むiOSアプリと拡張機能(ホストアプリではない)の間で通信する方法

TLDR:iOSアプリとの間でリアルタイムのメッセージや通知を送信することは可能ですか?拡張機能?

同じApp Groupの一部であり、同じCoreData(SQLiteデータベース)を共有する拡張子を持つiOSアプリを書いています。アプリと拡張機能からCoreDataを使用してデータベースの読み取りと書き込みを行うことができ、どちらも同じコンテンツを共有します。

私の質問は次のとおりです。アプリと拡張機能の間でメッセージや通知を送信して、必要に応じて更新するように相手に通知することはできますか?

NSNotificationCenterを介して通知を送信しようとしましたが、App/Extensionから「出力」されません。これは、共有NSUserDefaultsグループに書き込み、NSUserDefaultsDidChangeNotificationをリ​​ッスンしようとした場合と同じ問題です。これはアプリ内で機能しますが、拡張機能は何も受け取りません(起動され、同じNSUserDefaultsを共有していることがわかっている場合)。物事を同期させる方法はありますか?

23
Ludovic Landry

TLDR:いいえ、しかしハックがあります

拡張機能の有無にかかわらず、iOSアプリには真のプロセス間通信はありません。 NSDistributedNotificationはまだOSXからiOSに移行しておらず、おそらく移行しないでしょう。

一部の拡張機能タイプでは、NSExtensionContextを介してURLを開き、それらを使用して、URLを処理するアプリにデータを渡すことができます。これにより、アプリが前面に表示されますが、希望どおりに聞こえません。

ただし、必要なものを入手できる可能性のあるハックがあります。

  • ユーザーのデフォルトに書き込む代わりに、アプリグループディレクトリ内のファイルに書き込みます。
  • ファイルを直接書き込むだけでなく、NSFileCoordinatorを使用して実行しますcoordinatedファイルに書き込みます。
  • ファイルへの変更について知りたいオブジェクトにNSFilePresenterを実装し、必ず[NSFileCoordinator addFilePresenter:someObject]を呼び出してください。
  • オプションのpresentedItemDidChangeメソッドをファイルプレゼンターに実装します。

このすべての権利を実行すると、アプリまたは拡張機能のいずれかからこのファイルに書き込み、もう一方のファイルでpresentedItemDidChangeを自動的に呼び出すことができます。ボーナスとして、もちろんそのファイルの内容を読み取ることができるので、任意のデータをやり取りすることができます。

26
Tom Harrington

ホストアプリとアプリ拡張機能の間で汎用の双方向通信を行う別の方法については、MMWormholeを試してください。

http://www.mutualmobile.com/posts/mmwormholehttps://github.com/mutualmobile/MMWormhole

これはCFNotificationCenterのかなり軽量なラッパーであり、「Darwin」通知を使用してプロセス間通信を実行します( [〜#〜] ipc [〜#〜] )。

アプリの共有コンテナを使用してペイロードをやり取りし、ファイルを自分で作成する必要がある場合でもカプセル化します。

クラス(およびリポジトリ内のサンプルアプリ)はうまく機能しているようで、非常に反応が良いです。

これもお役に立てば幸いです。

7
RonDiamond

IOSまたはアプリと拡張機能の任意の2つのアプリ間で通信するために使用できるハックがあります。唯一のこと-Appleは、その中のI/Oをブロックしているため、NetworkExtensionでは機能しません。

この方法でDarwinNotificationCenterに通知を投稿できます。

    let notificationName = CFNotificationName("com.notification.name" as CFString)
    let notificationCenter = CFNotificationCenterGetDarwinNotifyCenter()

    CFNotificationCenterPostNotification(notificationCenter, notificationName, nil, nil, false)

アプリにオブザーバーを追加します。

    let notificationName = "com.notification.name" as CFString
    let notificationCenter = CFNotificationCenterGetDarwinNotifyCenter()

    CFNotificationCenterAddObserver(notificationCenter,
                                    nil,
                                    { (
                                        center: CFNotificationCenter?,
                                        observer: UnsafeMutableRawPointer?,
                                        name: CFNotificationName?,
                                        object: UnsafeRawPointer?,
                                        userInfo: CFDictionary?
                                        ) in

                                        print("Notification name: \(name)")
                                    },
                                    notificationName,
                                    nil,
                                    CFNotificationSuspensionBehavior.deliverImmediately)

いくつかのリンク: https://github.com/choefele/CCHDarwinNotificationCenter

https://developer.Apple.com/documentation/corefoundation/1542572-cfnotificationcentergetdarwinnot

https://developer.Apple.com/library/content/documentation/Darwin/Conceptual/MacOSXNotifcationOv/DarwinNotificationConcepts/DarwinNotificationConcepts.html

6
mafonya

私は同じ問題に苦しんでいて、きれいな解決策も見つけていません。これを解決するもう1つの厄介な方法は、拡張機能でタイマーを実行し、共有コンテナー設定/データベースの値を定期的にチェックしてから、必要に応じて更新することです。エレガントではありませんが、うまくいくようです。

2
jhnatow