本文介绍了Finder Sync Extension 和 Main App 应该如何通信?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的用例:我有一个用于同步文件的MainApp".我希望MainApp"处理所有有关同步的服务器调用和其他 REST API 调用,例如文档共享等.

My use case: I have a 'MainApp' which does the syncing of files.I would like that 'MainApp' handles all server calls regarding syncing and other REST API calls such as document-sharing, etc.

另一方面,我会有一个 Finder 同步扩展,它会显示同步状态图标覆盖.它还有一个文件上下文菜单项共享",它会显示一个共享对话框,用户可以在其中选择与谁共享文件.

On the other hand, I would have a Finder Sync Extension which would show sync-status icon overlays.It would also have a file-context-menu-item 'Share' which would present a Share dialog where users can choose with whom to share the file.

问题:

  1. FinderSyncExtension 和 MainApp 应该如何通信?是否应该使用 XCP,如果是,是否可以使用两种方式进行通信?例如 MainApp 通知 Finder 它应该刷新,因为一些文件已经同步,Finder 通知 MainApp 它应该执行共享"操作.

  1. How should FinderSyncExtension and MainApp communicate? Should XCP be utilised and if so, is it ok that communication is two-ways? For example MainApp informing Finder it should refresh because some files have been synced, and Finder informing MainApp that it should perform 'Share' operation.

谁应该展示分享"对话框?单击 FinderSyncExtension 的共享"菜单项时,应显示共享表单.这应该由 finder 扩展程序或 MainApp 显示(假设 FinderExtension 通知它共享"项已单击).

Who should present 'Share' dialog? When FinderSyncExtension 'Share' menu item is clicked, a Share form should be displayed. Should this be displayed by the finder extension or by the MainApp (assuming FinderExtension informed it that 'Share' item was clicked).

如果 Finder 扩展应该呈现表单,那么 FinderExtension 还应该从服务器检索数据(例如用于共享的联系人和组),我不确定 Finder 扩展是否应该对服务器执行任何网络调用.

If Finder extension should present the form, then FinderExtension should also retrieve data from the server (such as contacts and groups for sharing) and I'm not sure if Finder Extension should perform any network calls towards the server.

研究主题,我发现了几种方法:

Researching the topic, I found several approaches:

  1. FinderSyncExtension 和 MainApp 不直接通信.相反,FinderExtension 从数据库中读取数据以正确显示徽章.在这种情况下,尚不清楚 FinderExtension 在同步完成时应该如何更新,或者它应该如何通知 MainApp 执行某些操作.
  2. XPC 通信.我猜 FinderExtension 可以发起对 MainApp 的调用,但预期的方向相反?
  3. macOS 进程之间是否存在某种 NotificationCenter?我尝试使用 NSWorkspace.sharedWorkspace.notificationCenterNSDistributedNotificationCenter.defaultCenter 但它们似乎没有在 MainApp 中传递通知.
  4. 像 Seafile 项目中的 mach_ports?
  1. FinderSyncExtension and MainApp don't communicate directly. Instead, FinderExtension reads data from database to properly show badges. In this scenario it is unclear how FinderExtension should update when sync is finished or how should it inform MainApp to perform some action.
  2. XPC communication. I guess FinderExtension could initiate calls to MainApp but is opposite direction expected?
  3. Is there some kind of NotificationCenter between macOS processes? I tried with NSWorkspace.sharedWorkspace.notificationCenter and with NSDistributedNotificationCenter.defaultCenter but they don't seem to deliver notification in MainApp.
  4. mach_ports as in Seafile project?

推荐答案

我设法通过 CFMessagePort API 做到了这一点.为了让沙盒扩展程序和主应用程序进行通信,需要在 Xcode 功能中启用 AppGroups.此外,需要使用带后缀(由您选择)的应用组密钥作为消息端口标识符.

I managed to do this via CFMessagePort API. In order to have sandboxed extension and main app to communicate, AppGroups need to be enabled in Xcode capabilities. Additionally, app-group key with suffix (by your choice) needs to be used as message-port identifier.

在主应用程序的某处,这种代码会监听消息端口:

Somewhere in the main app, this kind of code would listen on message port:

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;
}

Finder 同步扩展

然后,在扩展中的某处(即当用户点击菜单项时):

Finder Sync Extension

And then, somewhere in the extension (ie when user taps on menu item):

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");
}

这将向主应用程序发送一条消息.

This will send a message to the main application.

这篇关于Finder Sync Extension 和 Main App 应该如何通信?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

06-23 14:24