首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在OSX上存储基于HTML的QuickLook生成器的首选项?

如何在OSX上存储基于HTML的QuickLook生成器的首选项?
EN

Stack Overflow用户
提问于 2015-05-01 12:32:47
回答 1查看 135关注 0票数 0

我曾经用一个必须单独安装的自定义PrefPane来完成这个任务,但这并不令人满意。

我有一个基于HTML的QuickLook生成器,它可以创建缩略图和一些非同质内容的预览(具有长的ASCII头的文件,以及不同数量的二进制扩展名,每个扩展名都带有一些头)。

在QL方法OSStatus GeneratePreviewForURL(void *thisInterface, QLPreviewRequestRef preview, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options)中,我尝试使用[NSUserDefaults standardUserDefaults],但它没有效果,也没有写入首选文件,这可能是因为我们在一个包中,而不是应用程序中。

知道如何做到这一点吗?我知道一些优秀的QL生成器可以做到这一点,比如BetterZip QL。我试图反向设计BetterZip QL,但没有成功。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-05-01 12:32:47

我直接联系了BetterZip QL的作者,我们一起想出了一个解决方案。这就是了。

简言之:

  1. 首先,创建一个小助手应用程序,它将被捆绑在生成器中。此应用程序将负责编写首选项文件。
  2. 使这个应用程序注册一个自定义的URL方案,并实现与它相关的处理。
  3. 使您的基于HTML的QL打开一个特殊格式的URL,使用该自定义方案,使用Javascript。

好的,现在详细说明。

首先,在Xcode工作区/项目中创建一个小助手应用程序目标。我的QL生成器名为QLFits,我选择了QLFitsConfig。

默认情况下,有一个与该应用程序相关的MainMenu.xib。留着吧。它是由Info.plist使用的,它可以用于调试。实际上,要调试自定义URL方案,您可以向该xib添加一个NSWindow,并放置可用于显示调试消息的标签。在调试此问题时,我没有找到任何其他方式来记录或显示调试消息。

但最后,你有一个小的没有窗口的应用程序。这个应用程序必须有两种配置。

  1. 表示此应用程序是代理的标志(见图)。它防止应用程序在运行时出现在文档中。
  2. 具有Editor角色的自定义URL方案的声明。还请参阅图中的示例(此处为qlfitsconfig)

接下来,应用程序的实现需要注册URL方案,以告诉系统有一个应用程序能够打开它。下面是我的"appDidFinishLaunching“方法在应用程序的AppDelegate中的实现。

有三个部分:自定义URL方案的处理程序的注册。NSUserDefaults对象的实例化,其套件名为,与QL生成器共享。最后,注册首选项的默认值(使用捆绑在应用程序中的.plist文件)。

代码语言:javascript
复制
- (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";

然后,应用程序需要对事件的触发采取行动。因此,必须对事件做一些事情,并使用该事件来存储首选项。以下是实现。请注意,该方法的签名必须是准确的,并不是因为我们在上面声明了它,而是因为这是系统唯一认可的签名。

代码语言:javascript
复制
- (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检查)。您可以在终端中键入以下命令以查看发生了什么:

代码语言:javascript
复制
$ open qlfitsconfig://save/option1=value1/option2=value2

如果您保留了上面提到的标签的窗口,您可以使用它们来显示/调试应用程序接收到的事件。

现在,回到QL发生器。在生成器的“构建阶段”中,将配置应用程序作为“目标依赖项”。此外,添加一个新的“复制文件”构建阶段(在复制捆绑资源构建阶段之后),以便在QL包中复制该助手应用程序(见图)。

现在,在代码中,更准确地说,在方法预览方法:OSStatus GeneratePreviewForURL(void *thisInterface, QLPreviewRequestRef preview, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options)中。

在开始时,我确保配置帮助应用程序实际上是在系统的启动服务中注册的。要找到它,必须使用QL生成器的包标识符。特别注意应用程序的URL是如何构造的,这是基于在构建阶段( Helpers目录)复制它的位置。

代码语言:javascript
复制
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实例来访问它们,前提是我们使用助手应用程序中定义的相同的套件名来初始化它。示例:

代码语言:javascript
复制
    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代码

代码语言:javascript
复制
<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>

alwaysShowHeadersInputshowSummaryInThumbnailsInput是我在HTML代码中复选框的'id‘。而保存按钮正在触发saveConfig函数。

该按钮必须在a标记中声明:

代码语言:javascript
复制
<a href="#" onClick="saveConfig(this);return true;" style="float:right;"><input id="save" type="button" value="Save"></a>

以下是我的QL窗口中的首选项:

等等!

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29986907

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档