7

私の使用例: ファイルの同期を行う「MainApp」があります。「MainApp」が、同期に関するすべてのサーバー呼び出しと、ドキュメント共有などのその他の REST API 呼び出しを処理することを希望します。

一方、同期ステータス アイコン オーバーレイを表示する Finder Sync Extension を用意します。また、ユーザーがファイルを共有する相手を選択できる共有ダイアログを表示するファイルコンテキストメニュー項目「共有」も含まれます。

質問:

  1. FinderSyncExtension と MainApp はどのように通信する必要がありますか? XCP を使用する必要がありますか?使用する場合、通信は双方向で問題ありませんか? たとえば、一部のファイルが同期されているため、更新する必要があることを Finder に通知する MainApp と、「共有」操作を実行する必要があることを Finder が MainApp に通知します。

  2. 「共有」ダイアログを表示するのは誰ですか? FinderSyncExtension の [共有] メニュー項目をクリックすると、共有フォームが表示されます。これは、ファインダー拡張機能または MainApp によって表示される必要があります (FinderExtension が「共有」項目がクリックされたことを通知したと仮定します)。

Finder 拡張機能がフォームを表示する必要がある場合、FinderExtension はサーバーからデータ (共有用の連絡先やグループなど) も取得する必要があり、Finder 拡張機能がサーバーに対してネットワーク呼び出しを実行する必要があるかどうかはわかりません。

このトピックを調査したところ、いくつかのアプローチが見つかりました。

  1. FinderSyncExtension と MainApp は直接通信しません。代わりに、FinderExtension はデータベースからデータを読み取り、バッジを適切に表示します。このシナリオでは、同期が完了したときに FinderExtension を更新する方法や、なんらかのアクションを実行するように MainApp に通知する方法が不明です。
  2. XPC通信。FinderExtension は MainApp への呼び出しを開始できると思いますが、逆方向が予想されますか?
  3. macOS プロセス間に何らかの種類の NotificationCenter がありますか? 試してみましたが、MainApp で通知を配信NSWorkspace.sharedWorkspace.notificationCenterNSDistributedNotificationCenter.defaultCenterていないようです。
  4. Seafile プロジェクトのような mach_ports?
4

2 に答える 2

7

CFMessagePortAPIを介してこれを行うことができました。サンドボックス化された拡張機能とメイン アプリが通信できるようにするには、AppGroups を Xcode 機能で有効にする必要があります。さらに、(選択した) サフィックス付きのアプリ グループ キーをメッセージ ポート識別子として使用する必要があります。

メインアプリ

メイン アプリのどこかで、この種のコードはメッセージ ポートでリッスンします。

CFMessagePortRef port = CFMessagePortCreateLocal(nil, CFSTR("group.com.yourapp.mach_or_something"), Callback, nil,
                                                 nil);
CFRunLoopSourceRef runLoopSource = CFMessagePortCreateRunLoopSource(nil, port, 0);
CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopCommonModes);

Callback次のように実装されるメソッドです。

static CFDataRef Callback(CFMessagePortRef port, SInt32 messageID, CFDataRef data, void* info)
{
    NSData* objcData = (__bridge NSData*) data;
    NSLog(@"Message received: %@", [NSString.alloc initWithData:objcData encoding:NSASCIIStringEncoding]);
    return data;
}

ファインダー同期拡張機能

そして、拡張機能のどこか (つまり、ユーザーがメニュー項目をタップしたとき):

CFDataRef data = CFDataCreate(NULL, (const UInt8*) "somedata", 8);
SInt32 messageID = 0x1111; // Arbitrary
CFTimeInterval timeout = 1;

CFMessagePortRef remotePort = CFMessagePortCreateRemote(nil, CFSTR("group.com.yourapp.mach_or_something"));

SInt32 status = CFMessagePortSendRequest(remotePort, messageID, data, timeout, timeout, NULL, NULL);
if (status == kCFMessagePortSuccess)
{
    NSLog(@"SUCCESS STATUS");
}
else
{
    NSLog(@"FAIL STATUS");
}

これにより、メイン アプリケーションにメッセージが送信されます。

于 2016-12-15T13:55:47.570 に答える