我曾经用一个必须单独安装的自定义PrefPane来完成这个任务,但这并不令人满意。
我有一个基于HTML的QuickLook生成器,它可以创建缩略图和一些非同质内容的预览(具有长的ASCII头的文件,以及不同数量的二进制扩展名,每个扩展名都带有一些头)。
在QL方法OSStatus GeneratePreviewForURL(void *thisInterface, QLPreviewRequestRef preview, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options)中,我尝试使用[NSUserDefaults standardUserDefaults],但它没有效果,也没有写入首选文件,这可能是因为我们在一个包中,而不是应用程序中。
知道如何做到这一点吗?我知道一些优秀的QL生成器可以做到这一点,比如BetterZip QL。我试图反向设计BetterZip QL,但没有成功。
发布于 2015-05-01 12:32:47
我直接联系了BetterZip QL的作者,我们一起想出了一个解决方案。这就是了。
简言之:
好的,现在详细说明。
首先,在Xcode工作区/项目中创建一个小助手应用程序目标。我的QL生成器名为QLFits,我选择了QLFitsConfig。
默认情况下,有一个与该应用程序相关的MainMenu.xib。留着吧。它是由Info.plist使用的,它可以用于调试。实际上,要调试自定义URL方案,您可以向该xib添加一个NSWindow,并放置可用于显示调试消息的标签。在调试此问题时,我没有找到任何其他方式来记录或显示调试消息。
但最后,你有一个小的没有窗口的应用程序。这个应用程序必须有两种配置。
Editor角色的自定义URL方案的声明。还请参阅图中的示例(此处为qlfitsconfig)

接下来,应用程序的实现需要注册URL方案,以告诉系统有一个应用程序能够打开它。下面是我的"appDidFinishLaunching“方法在应用程序的AppDelegate中的实现。
有三个部分:自定义URL方案的处理程序的注册。NSUserDefaults对象的实例化,其套件名为,与QL生成器共享。最后,注册首选项的默认值(使用捆绑在应用程序中的.plist文件)。
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
NSAppleEventManager *appleEventManager = [NSAppleEventManager sharedAppleEventManager];
[appleEventManager setEventHandler:self andSelector:@selector(handleAppleEvent:withReplyEvent:) forEventClass:kInternetEventClass andEventID:kAEGetURL];
[[NSUserDefaults standardUserDefaults] addSuiteNamed:suiteName];
NSUserDefaults *defaults = [[NSUserDefaults alloc] initWithSuiteName:suiteName];
NSString *optionsPath = [[NSBundle mainBundle] pathForResource:@"defaultOptions" ofType:@"plist"];
NSDictionary *defaultOptions = [NSDictionary dictionaryWithContentsOfFile:optionsPath];
[defaults registerDefaults:defaultOptions];
}suiteName变量是一个具有反向DNS格式的静态NSString:static NSString *suiteName = @"com.onekiloparsec.qlfitsconfig.user-defaults-suite";。
然后,应用程序需要对事件的触发采取行动。因此,必须对事件做一些事情,并使用该事件来存储首选项。以下是实现。请注意,该方法的签名必须是准确的,并不是因为我们在上面声明了它,而是因为这是系统唯一认可的签名。
- (void)handleAppleEvent:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent
{
NSString *URLString = [[event paramDescriptorForKeyword:keyDirectObject] stringValue];
if (URLString) {
NSURL *URL = [NSURL URLWithString:URLString];
if (URL) {
NSUserDefaults *defaults = [[NSUserDefaults alloc] initWithSuiteName:suiteName];
for (NSString *component in [URL pathComponents]) {
if ([component containsString:@"="]) {
NSArray *keyValue = [component componentsSeparatedByString:@"="];
[defaults setObject:keyValue.lastObject forKey:keyValue.firstObject];
}
}
[defaults synchronize];
}
}
}基本思想是,我们将提供首选项通过URL参数作为键值对。因此,我们在这里将URL字符串转换为一对首选项,这些首选项存储为字符串。
这就是应用程序的全部。要测试和调试它,您需要构建和运行它(例如,请与它正在运行的/实用程序/活动Monitor.app检查)。您可以在终端中键入以下命令以查看发生了什么:
$ open qlfitsconfig://save/option1=value1/option2=value2如果您保留了上面提到的标签的窗口,您可以使用它们来显示/调试应用程序接收到的事件。
现在,回到QL发生器。在生成器的“构建阶段”中,将配置应用程序作为“目标依赖项”。此外,添加一个新的“复制文件”构建阶段(在复制捆绑资源构建阶段之后),以便在QL包中复制该助手应用程序(见图)。

现在,在代码中,更准确地说,在方法预览方法:OSStatus GeneratePreviewForURL(void *thisInterface, QLPreviewRequestRef preview, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options)中。
在开始时,我确保配置帮助应用程序实际上是在系统的启动服务中注册的。要找到它,必须使用QL生成器的包标识符。特别注意应用程序的URL是如何构造的,这是基于在构建阶段( Helpers目录)复制它的位置。
NSBundle *bundle = [NSBundle bundleWithIdentifier:@"com.onekiloparsec.QLFits3"];
NSURL *urlConfig = [NSURL fileURLWithPath:[[bundle bundlePath] stringByAppendingPathComponent:@"Contents/Helpers/QLFitsConfig.app"]];
LSRegisterURL((__bridge CFURLRef) urlConfig, true);最后一行是使用遗留API,但我无法使新的API工作。这是一个弱点,人们可能会在某个时候找到一个更好的方法。
现在,如果已经保存了一些首选项,我们可以使用NSUserDefaults实例来访问它们,前提是我们使用助手应用程序中定义的相同的套件名来初始化它。示例:
static NSString *suiteName = @"com.onekiloparsec.qlfitsconfig.user-defaults-suite";
NSUserDefaults *defaults = [[NSUserDefaults alloc] initWithSuiteName:suiteName];
BOOL alwaysShowHeaders = YES;
if ([defaults stringForKey:@"alwaysShowHeaders"]) {
alwaysShowHeaders = [[defaults stringForKey:@"alwaysShowHeaders"] isEqualToString:@"1"];
}对Obj代码来说就是这样了。
最后一部分是Javascript代码。在我的QL生成器(其代码可以在GitHub上检查)中,我使用一个包含所有html和JS代码的template.html文件。你可以在这里以不同的方式组织自己。
我最初打算在切换复选框时更改QL首选项。但它似乎不起作用(没有事件被触发)。我让它工作的唯一方法是,一旦设置了复选框,用户就会被要求使用一个按钮“保存”首选项。我在点击那个按钮的时候保存了首选项。以下是我的template.html中的JS代码
<script>
function saveConfig (a) {
a.href = "qlfitsconfig://save";
a.href += "/alwaysShowHeaders=" + (document.getElementById("alwaysShowHeadersInput").checked ? "1" : "0");
a.href += "/showSummaryInThumbnails=" + (document.getElementById("showSummaryInThumbnailsInput").checked ? "1" : "0");
return true;
}
</script>alwaysShowHeadersInput和showSummaryInThumbnailsInput是我在HTML代码中复选框的'id‘。而保存按钮正在触发saveConfig函数。
该按钮必须在a标记中声明:
<a href="#" onClick="saveConfig(this);return true;" style="float:right;"><input id="save" type="button" value="Save"></a>以下是我的QL窗口中的首选项:

等等!
https://stackoverflow.com/questions/29986907
复制相似问题