2011-07-03 18 views
7

私のアプリケーションにカスタムURLスキームを実装しようとしています。 Info.plistに必要な行を追加しました。指定されたURL(例:myapp://)を呼び出した後、アプリケーションが起動します。URLスキーム - Qt and mac

私はURLを処理したい場合は、私はこれらの手順を見つけた:

@interface EventHandler : NSObject { 
} 
@end 

@implementation EventHandler 
- (id)init { 
    self = [super init]; 

    if (self) { 
     NSLog(@"eventHandler::init"); 

     NSNotificationCenter* defaultCenter = [NSNotificationCenter defaultCenter]; 
     [defaultCenter addObserver:self 
         selector:@selector(applicationDidFinishLaunching:) 
//      name:NSApplicationWillFinishLaunchingNotification 
      name:NSApplicationDidFinishLaunchingNotification 
         object:nil]; 
    } 
    return self; 
} 

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

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

@end 

上記のコードは、アプリケーションが実行されている場合に取り組んでいるが、URLが呼び出されると、アプリケーションが終了した場合には、イベントは捕捉されません。これはNSApplicationDidFinishLaunchingNotificationのためです。 NSApplicationWillFinishLaunchingNotificationに変更すると、非イベントが捕捉されます。たぶん私の前でQtが処理しているかもしれませんが、問題の回避策を見つけることができません。

+0

それはそのリスニングようですNSApplicationDidBecomeActiveNotification通知は問題を解決します。 私はそれが最善の方法だとは思わないので、私はいくつかのより良いアイデアのために質問を開いたままにしています:) – birmacher

答えて

4

QtベースのアプリケーションでMac上でカスタムURLスキームを処理しようとしていて、元のポスターと同じパスになってしまいました。 Qt4はすでにMac上でURLイベントをサポートしているので、Objective-Cコードを受け取る必要はありません。これは実際には、NSApplicationWillFinishLaunchingNotificationに応答してイベントハンドラを設定したときにURLイベントを受け取らなかった理由です。Qtは後で自身のハンドラを登録します。

カスタムスキームのURLがトリガーされると、QtアプリケーションはFileOpenEventを受け取ります。イベントを受け取るのはQApplicationインスタンスです。アプリケーションをサブクラスQApplicationにするか、または標準QApplicationにイベント・フィルターをインストールすることで、それを捕まえることができます。私はこの第2のアプローチを選択しました。

私のカスタムイベントフィルタクラスFileOpenEventFilterのeventFilterメソッドを次に示します。イベントに空でないURLが含まれている場合、信号urlOpenedが送出されます。また、私のメインウィンドウが完全にイベントが到着したときに初期化されていない場合の最後の開かれたURLを保存します(カスタムURLがクリックされたときに、それが実行されていないとき、私のアプリで発生している。)

bool FileOpenEventFilter::eventFilter(QObject* obj, QEvent* event) 
{ 
    if (event->type() == QEvent::FileOpen) 
    { 
     QFileOpenEvent* fileEvent = static_cast<QFileOpenEvent*>(event); 
     if (!fileEvent->url().isEmpty()) 
     { 
      m_lastUrl = fileEvent->url().toString(); 
      emit urlOpened(m_lastUrl); 
     } 
     else if (!fileEvent->file().isEmpty()) 
     { 
      emit fileOpened(fileEvent->file()); 
     } 

     return false; 
    } 
    else 
    { 
     // standard event processing 
     return QObject::eventFilter(obj, event); 
    } 
} 
1

私のアプリケーションハンドラは、アプリケーションデリゲートのapplicationWillFinishLaunching:メソッドに登録します。私はイベントを見逃しません。 EventHandlerオブジェクトを初期化して、その通知を受け取るのが遅すぎる可能性があります。それを別のクラスとして保持したい場合は、それは問題ありませんが、オブジェクトを作成して、アプリケーション代理人のメソッド内にNSAppleEventManagerという名前で登録する必要があります。

関連する問題