How to handle with a default URL scheme

前端 未结 5 428
花落未央
花落未央 2020-11-27 13:23

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

I do a LSSetDefaultHandlerForURLScheme() in my + (void)initialize and I setted the s

相关标签:
5条回答
  • 2020-11-27 14:21

    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/kAEGetURL event.

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

    0 讨论(0)
  • 2020-11-27 14:22

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

    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)")
        }
    }
    
    0 讨论(0)
  • 2020-11-27 14:26

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

    A simple way to register and use a custom URL scheme is to define the scheme in your .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:

    [[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.

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

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

    Apple's documentation: Installing a Get URL Handler

    Update I 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:

    - (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

    0 讨论(0)
  • 2020-11-27 14:27

    All credits should go to weichsel and kch

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

    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)")
        }
    }
    
    0 讨论(0)
  • 2020-11-27 14:28

    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

    <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:

    - (void)handleGetURLScriptCommand:(NSScriptCommand *)command { … }
    
    0 讨论(0)
提交回复
热议问题