iOS 和 macOS 有一个名为通用剪贴板的内置功能,可以使用 iCloud 在设备之间同步剪贴板的内容。
NSPasteboard.general.clearContents()
NSPasteboard.general.writeObjects("Test 123")
我想在我的 Cocoa 应用程序上的通用粘贴板上写一些东西,以便在应用程序之间共享它,而不需要与其他 iCloud 设备同步。我无法找到办法做到这一点。事实上,我认为如果用户没有在设置中手动禁用它,这是不可能的。
文档说:
通过通用类方法提供的通用粘贴板会自动参与 macOS 10.12 及更高版本以及 iOS 10.0 及更高版本中的通用剪贴板功能。没有用于与此功能交互的 macOS API。 https://developer.apple.com/documentation/appkit/nspasteboard
但也许有一个解决方法,一个私有 API(我知道没有 App Store)或其他人可能知道的东西。 :)
干杯
是的,通用粘贴板可供所有应用程序使用,但 NSPasteboard 可用于创建私有粘贴板。您需要做的就是:
let myPasteboard = NSPasteboard(name: NSPasteboard.Name("mypasteboard"))
您可以在此处查看文档。因此,您可以将粘贴的项目复制到您的私人粘贴板,并且只有当您需要时,您才可以将数据传输到通用粘贴板并使数据可供所有应用程序使用。
但是,如果您想阻止通用剪贴板在设备之间共享,您所要做的就是:
let generalPasteboard = NSPasteboard.general
// current host only
generalPasteboard.prepareForNewContents(with: .currentHostOnly)
// write here to the pasteboard
对于活动用户会话,请使用 SCDynamicStoreCopyConsoleUser。 该库是 libplist,它是跨平台的。此代码允许您禁用或启用剪贴板共享。纯C++代码。
// Assemble some arguments
const std::string plistPath = "/Users/" + activeUserSession + "/Library/Preferences/com.apple.coreservices.useractivityd.plist";
const std::string baseCommand = "defaults write ~/Library/Preferences/com.apple.coreservices.useractivityd.plist ClipboardSharingEnabled";
plist_t root_node = NULL;
// Read the plist file
int status = plist_read_from_file(plistPath.c_str(), &root_node, NULL);
// File doesn't exist, let's write a flag with the feature enabled (as that is the default value on mac)
if (status)
{
// Create a new beautiful dictionary
plist_t dict = plist_new_dict();
// Set the initial value for ClipboardSharingEnabled to "1"
plist_dict_set_item(dict, "ClipboardSharingEnabled", plist_new_string("1"));
// Write the plist to the file
status = plist_write_to_file(dict, plistPath.c_str(), PLIST_FORMAT_BINARY, PLIST_OPT_NONE);
if (status != PLIST_ERR_SUCCESS)
{
// If our file attempt for some reason would fail, let's try it with the shell as well just in case...
status = system((baseCommand + " " + "1").c_str());
}
// Free
plist_free(dict);
// PLIST_ERR_SUCCESS is 0, so success applies for system() call as well
if (status != PLIST_ERR_SUCCESS)
throw here
}
// Prepare for reading
plist_t read_root_node = NULL;
plist_format_t originalFormat;
status = plist_read_from_file(plistPath.c_str(), &read_root_node, &originalFormat);
char *clipboardSharingValue = NULL;
// If read was successful
if (status == PLIST_ERR_SUCCESS)
{
// Check if the ClipboardSharingEnabled key exists and It's an actual string
plist_t clipboardSharingEnabledItem = plist_dict_get_item(read_root_node, "ClipboardSharingEnabled");
if (clipboardSharingEnabledItem && plist_get_node_type(clipboardSharingEnabledItem) == PLIST_STRING)
{
// Retrieve the current value
plist_get_string_val(clipboardSharingEnabledItem, &clipboardSharingValue);
}
// Check state
bool isEnabled = std::string(clipboardSharingValue) == "1";
if (isEnabled != enableClipboardSharing)
{
// Determine value to set
const std::string valueToSet = enableClipboardSharing ? "1" : "0";
// Write the desired value (0/1) as a string to ClipboardSharingEnabled in read_root_node and save
plist_dict_set_item(read_root_node, "ClipboardSharingEnabled", plist_new_string(valueToSet.c_str()));
// Save the updated plist to the file
status = plist_write_to_file(read_root_node, plistPath.c_str(), originalFormat, PLIST_OPT_NONE);
if (status != PLIST_ERR_SUCCESS)
// If our file attempt for some reason would fail, let's try it with the shell as well just in case...
status = system((baseCommand + " " + valueToSet).c_str());
}
// Destruct a plist_t node and all its children recursively
plist_free(read_root_node);
// PLIST_ERR_SUCCESS is 0, so success applies for system() call as well
if (status != PLIST_ERR_SUCCESS)
throw here
}
else
throw here