URL方案 - Qt和mac

时间:2011-07-03 07:30:02

标签: cocoa qt macos url

我正在尝试为我的应用程序实现自定义URL方案。我为Info.plist添加了必要的行。在调用指定的url(例如:myapp://)后,应用程序将启动。

如果我想处理这个网址,我发现了以下步骤:

@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在我之前处理它,但我找不到解决问题的方法。

2 个答案:

答案 0 :(得分:5)

我还试图让我的基于Qt的应用程序在Mac上处理自定义URL方案,并沿着与原始海报相同的路径。事实证明,Qt4已经支持Mac上的URL事件,并且不需要编写Objective-C代码来接收它们。事实上,当您为响应NSApplicationWillFinishLaunchingNotification而设置事件处理程序时,您没有收到任何URL事件:Qt之后注册了自己的处理程序。

当触发包含自定义方案的URL时,您的Qt应用程序将收到FileOpenEvent。请注意,它是接收事件的QApplication实例。您可以通过创建应用程序子类QApplication或在标准QApplication上安装事件过滤器来捕获它。我选择了第二种方法。

这是我的自定义事件过滤器类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 :(得分:1)

我在我的应用程序委托的applicationWillFinishLaunching:方法中注册我的处理程序,我不会错过任何事件。您可能太晚初始化EventHandler对象以获取该通知。如果你想把它保存为一个单独的类,那没关系,但是你应该创建你的对象并在应用程序委托的NSAppleEventManager方法中用applicationWillFinishLaunching:注册它。