macos 如何处理默认 URL 方案

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1991072/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 06:38:26  来源:igfitidea点击:

How to handle with a default URL scheme

macoscocoaurl-schemeappkit

提问by papr

I want to build URI (or URL scheme) support in my app.

我想在我的应用程序中构建 URI(或 URL 方案)支持。

I do a LSSetDefaultHandlerForURLScheme()in my + (void)initializeand I setted the specific URL schemes also in my info.plist. So I have URL schemes without Apple Scriptor Apple Events.

LSSetDefaultHandlerForURLScheme()在 my 中做了一个,我+ (void)initialize也在我的info.plist. 所以我有没有Apple Script或 的URL 方案Apple Events

When I call myScheme:in my favorite browser the system activates my app.

当我调用myScheme:我最喜欢的浏览器时,系统会激活我的应用程序。

The problem is, how to handle the schemes when they are called. Or better said: How can I define what my app should do, when myScheme:is called.

问题是,如何在调用时处理这些方案。或者更好地说:我如何定义我的应用程序应该做什么,何时myScheme:被调用。

Is there a special method that I have to implement or do I have to register one somewhere?

是否有我必须实施的特殊方法,或者我必须在某处注册一个方法?

回答by Thomas Zoechling

As you are mentioning AppleScript, I suppose you are working on Mac OS X.

当您提到 AppleScript 时,我想您正在使用 Mac OS X。

A simple way to register and use a custom URL scheme is to define the scheme in your .plist:

注册和使用自定义 URL 方案的一种简单方法是在 .plist 中定义方案:

<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleURLName</key>
        <string>URLHandlerTestApp</string>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>urlHandlerTestApp</string>
        </array>
    </dict>
</array>

To register the scheme, put this in your AppDelegate's initialization:

要注册该方案,请将其放在 AppDelegate 的初始化中:

[[NSAppleEventManager sharedAppleEventManager]
    setEventHandler:self
        andSelector:@selector(handleURLEvent:withReplyEvent:)
      forEventClass:kInternetEventClass
         andEventID:kAEGetURL];

Whenever your application gets activated via URL scheme, the defined selector gets called.

每当您的应用程序通过 URL 方案激活时,就会调用定义的选择器。

A stub for the event-handling method, that shows how to get the URL string:

事件处理方法的存根,显示如何获取 URL 字符串:

- (void)handleURLEvent:(NSAppleEventDescriptor*)event
        withReplyEvent:(NSAppleEventDescriptor*)replyEvent
{
    NSString* url = [[event paramDescriptorForKeyword:keyDirectObject]
                        stringValue];
    NSLog(@"%@", url);
}

Apple's documentation: Installing a Get URL Handler

Apple 的文档:安装获取 URL 处理程序

UpdateI just noticed a problem for sandboxed apps that install the event handler in applicationDidFinishLaunching:. With enabled sandboxing, the handler method doesn't get called when the app is launched by clicking a URL that uses the custom scheme. By installing the handler a bit earlier, in applicationWillFinishLaunching:, the method gets called as expected:

更新我刚刚注意到在applicationDidFinishLaunching:. 启用沙箱后,在通过单击使用自定义方案的 URL 启动应用程序时,不会调用处理程序方法。通过稍早安装处理程序,在 中applicationWillFinishLaunching:,该方法将按预期调用:

- (void)applicationWillFinishLaunching:(NSNotification *)aNotification
{
    [[NSAppleEventManager sharedAppleEventManager]
        setEventHandler:self
            andSelector:@selector(handleURLEvent:withReplyEvent:)
          forEventClass:kInternetEventClass
             andEventID:kAEGetURL];
}

- (void)handleURLEvent:(NSAppleEventDescriptor*)event
        withReplyEvent:(NSAppleEventDescriptor*)replyEvent
{
    NSString* url = [[event paramDescriptorForKeyword:keyDirectObject]
                        stringValue];
    NSLog(@"%@", url);
}


On the iPhone, the easiest way to handle URL-scheme activation is, to implement UIApplicationDelegate's application:handleOpenURL:- Documentation

在 iPhone 上,处理 URL-scheme 激活的最简单方法是实现 UIApplicationDelegate 的application:handleOpenURL:-文档

回答by Laimis

All credits should go to weichseland kch

所有的学分应该去weichselKCH

I'm just adding swift(2.2/3.0) code for your convenience

为了您的方便,我只是添加了 swift(2.2/3.0) 代码

func applicationWillFinishLaunching(_ notification: Notification) {
    NSAppleEventManager.shared().setEventHandler(self, andSelector: #selector(self.handleGetURL(event:reply:)), forEventClass: UInt32(kInternetEventClass), andEventID: UInt32(kAEGetURL) )
}

func handleGetURL(event: NSAppleEventDescriptor, reply:NSAppleEventDescriptor) {
    if let urlString = event.paramDescriptor(forKeyword: keyDirectObject)?.stringValue {
        print("got urlString \(urlString)")
    }
}

回答by Peter Hosey

The problem is, how to handle the schemes when they are called.

问题是,如何在调用时处理这些方案。

That's where the Apple Events come in. When Launch Services wants your app to open a URL, it sends your app a kInternetEventClass/kAEGetURLevent.

这就是 Apple 事件的用武之地。当 Launch Services 想要您的应用程序打开一个 URL 时,它会向您的应用程序发送一个kInternetEventClass/kAEGetURL事件。

The Cocoa Scripting Guideuses this very task as an example of installing an event handler.

Cocoa 脚本指南使用这个任务作为安装事件处理程序的示例

回答by Martin Pilch

I'm just adding slightly different Swift 4/5 version of the code:

我只是添加了稍微不同的 Swift 4/5 版本的代码:

func applicationWillFinishLaunching(_ notification: Notification) {
    NSAppleEventManager
        .shared()
        .setEventHandler(
            self,
            andSelector: #selector(handleURL(event:reply:)),
            forEventClass: AEEventClass(kInternetEventClass),
            andEventID: AEEventID(kAEGetURL)
        )

}

@objc func handleURL(event: NSAppleEventDescriptor, reply: NSAppleEventDescriptor) {
    if let path = event.paramDescriptor(forKeyword: keyDirectObject)?.stringValue?.removingPercentEncoding {
        NSLog("Opened URL: \(path)")
    }
}

回答by Chris Page

You can define the “get URL” command in a scripting terminology SDEF and implement the corresponding method. For example, Terminal's SDEF contains the following command definition for handling URLs

您可以在脚本术语 SDEF 中定义“获取 URL”命令并实现相应的方法。例如,终端的 SDEF 包含以下用于处理 URL 的命令定义

<command name="get URL" code="GURLGURL" description="Open a command an ssh, telnet, or x-man-page URL." hidden="yes">
    <direct-parameter type="text" description="The URL to open." />
</command>

and declares that the application responds to it:

并声明应用程序响应它:

<class name="application" code="capp" description="The application's top-level scripting object.">
    <cocoa class="TTApplication"/>
    <responds-to command="get URL">
        <cocoa method="handleGetURLScriptCommand:" />
    </responds-to>
</class>

The TTApplication class (a subclass of NSApplication) defines the method:

TTApplication 类(NSApplication 的子类)定义了方法:

- (void)handleGetURLScriptCommand:(NSScriptCommand *)command { … }