Как работать со схемой URL по умолчанию

Я хочу создать поддержку URI (или схемы URL) в моем приложении.

Я делаю LSSetDefaultHandlerForURLScheme() в моем + (void)initialize и я установил конкретные схемы URL также в моем info.plist, Так что у меня есть схемы URL без Apple Script или же Apple Events,

Когда я звоню myScheme: в моем любимом браузере система активирует мое приложение.

Проблема в том, как обращаться со схемами, когда они вызываются. Или лучше сказать: как я могу определить, что должно делать мое приложение, когда myScheme: называется.

Есть ли какой-то особый метод, который я должен внедрить, или я должен где-нибудь его зарегистрировать?

4 ответа

Решение

Поскольку вы упоминаете AppleScript, я полагаю, вы работаете на Mac OS X.

Простой способ зарегистрироваться и использовать собственную схему URL-адреса - определить схему в вашем.plist:

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

Чтобы зарегистрировать схему, поместите это в инициализацию вашего AppDelegate:

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

Всякий раз, когда ваше приложение активируется через схему URL, вызывается определенный селектор.

Заглушка для метода обработки событий, который показывает, как получить строку URL:

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

Документация Apple: установка обработчика URL-адресов

Обновление Я только что заметил проблему для изолированных приложений, которые устанавливают обработчик событий в 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);
}

На iPhone самый простой способ справиться с активацией URL-схемы - реализовать UIApplicationDelegate. application:handleOpenURL: - Документация

Все кредиты должны идти в Weichsel и KCH

Я просто добавляю код 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)")
    }
}

Проблема в том, как обращаться со схемами, когда они вызываются.

Вот тут и появляются события Apple. Когда Launch Services хочет, чтобы ваше приложение открыло URL, оно отправляет ваше приложение kInternetEventClass/kAEGetURL событие.

Руководство по написанию сценариев Cocoa использует эту задачу в качестве примера установки обработчика событий.

Я просто добавляю немного другую версию кода 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)")
    }
}

Вы можете определить команду "get URL" в терминологии сценариев SDEF и реализовать соответствующий метод. Например, 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>

и заявляет, что приложение отвечает на него:

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

Класс TTApplication (подкласс NSApplication) определяет метод:

- (void)handleGetURLScriptCommand:(NSScriptCommand *)command { … }
Другие вопросы по тегам