アプリでURI(またはURLスキーム)サポートを構築したい。
LSSetDefaultHandlerForURLScheme()
で+ (void)initialize
を実行し、info.plist
でも特定のURLスキームを設定しました。だから私はApple Script
またはApple Events
のないURLスキームを持っています。
お気に入りのブラウザでmyScheme:
を呼び出すと、システムがアプリをアクティブにします。
問題は、呼び出されたときにスキームをどのように処理するかです。または、より適切に言うと、myScheme:
が呼び出されたときに、アプリが何をすべきかをどのように定義できますか。
実装しなければならない特別なメソッドはありますか、それともどこかに登録する必要がありますか?
AppleScriptについておっしゃっていますが、Mac OSXで作業していると思います。
カスタム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のドキュメント: Get URLハンドラーのインストール
UpdateapplicationDidFinishLaunching:
にイベントハンドラーをインストールするサンドボックス化されたアプリの問題に気づきました。サンドボックスを有効にすると、カスタムスキームを使用する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:
-- Documentation を実装することです。
すべてのクレジットは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イベントが発生します。LaunchServicesがアプリにURLを開くように要求すると、アプリにkInternetEventClass
/kAEGetURL
イベントが送信されます。
スクリプト用語SDEFで「getURL」コマンドを定義し、対応するメソッドを実装できます。たとえば、ターミナルの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 { … }
わずかに異なる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)")
}
}