我遇到了一个问题,后台应用程序使用LSUIElement = 1隐藏其停靠项,菜单栏并阻止它出现在Command-Tab应用程序切换器中。
它似乎只是雪豹的问题。
应用程序在菜单栏中放置一个NSStatusItem,并在单击时弹出一个菜单。选择“首选项...”应该会显示带有首选项的NSWindow。
看起来不起作用的第一件事是Window没有在前面订购,而是出现在所有其他应用程序窗口后面。
我试着通过打电话来解决这个问题
[[NSApplication sharedApplication] activateIgnoringOtherApps: YES]
但那没用。
过了一会儿,我发现菜单阻止了发送到运行循环的消息,所以我在MainController上写了另一个方法并发送了一个延迟的消息:
[self performSelector:@selector(setFront :)
withObject:[preferencesController window] afterDelay:1.0];
-(void)setFront: (id) theWindow {
[[NSApplication sharedApplication]activateIgnoringOtherApps:YES];
[theWindow orderFrontRegardless];
[theWindow makeKeyWindow];
[[NSApplication sharedApplication] activateIgnoringOtherApps:YES];
}
请注意send-every-possible-message-to-make-it-do-it-it-it-doing-doing方法。
这种方法很有效,窗口在所有应用程序的所有其他窗口的顶部显示,但大部分时间它都不活动,这意味着它的标题栏显示为灰色。单击标题栏也不会使窗口处于活动状态。单击窗口的内部将激活它!?
这一切在Leopard中似乎都不是问题;只是调用activateIgnoringOtherApps并使窗口键似乎工作得很好。
在Snow Leopard中有一个新的API,用于替换应该模拟其行为的LSUIElement:
http://developer.apple.com/mac/library/releasenotes/cocoa/appkit.html
我已经玩过了,但它只是SL,我无法设置LSUIElement。
这很奇怪 - 我正在Snow Leopard下写一个LSUIElement应用程序,我没有你所描述的问题......我确实遇到了新创建的窗口没有出现在前面的问题,但是我通过调用activateIgnoringOtherApps修复它。这就是我必须要做的就是让它按原样运作:
[NSApp activateIgnoringOtherApps: YES];
[preferencesWindow makeKeyAndOrderFront: self];
我甚至没有触及名字中有“政策”的任何东西。
在绝望中发布问题之后,我确实继续寻找并最终找到了解决方案。由于这让我困扰了几天,谷歌似乎找不到其他答案,我将解释“后代”的解决方案。
Snow Leopard添加了一个新的NSApplication presentationOptions API:
http://developer.apple.com/mac/library/releasenotes/cocoa/appkit.html
这应该模拟LSUIElement的工作方式,但提供更多的开发人员控制。不幸的是,模拟并不完美,因此10.5和10.6之间的行为发生了变化。
特别是,如果您的应用程序在其info.plist中具有LSUIElement = 1行,则Snow Leopard将“将应用程序的presentationOptions ..初始化为NSApplicationPresentationOptions标志的等效组合”。
只有它不是真的。它将新的NSApplication setActivationPolicy设置为NSApplicationActivationPolicyAccessory:
“应用程序没有出现在Dock中,也没有菜单栏,但可以通过编程方式或通过单击其中一个窗口来激活它。这对应于应用程序的Info.plist中的LSUIElement键值为1。”
尽管提到以编程方式激活,但activateIgnoringOtherApps:完全被忽略。
解决方案是将激活策略设置为“常规”:
[[NSApplication sharedApplication] setActivationPolicy: NSApplicationActivationPolicyRegular];
当然,如果你使用10.6 SDK作为Base SDK,那么你只能这样做,这是目前很少有人想做的事情,所以下面是10.5安全的方法:
NSApplication* app = [NSApplication sharedApplication];
if( [app respondsToSelector: @selector(setActivationPolicy:)] ) {
NSMethodSignature* method = [[app class] instanceMethodSignatureForSelector: @selector(setActivationPolicy:)];
NSInvocation* invocation = [NSInvocation invocationWithMethodSignature: method];
[invocation setTarget: app];
[invocation setSelector: @selector(setActivationPolicy:)];
NSInteger myNSApplicationActivationPolicyAccessory = 0;
[invocation setArgument: &myNSApplicationActivationPolicyAccessory atIndex: 2];
[invocation invoke];
}
我希望有人会觉得这很有用。