我正在设计辅助工具。
它将获得具有文本焦点的当前窗口:
self.app_with_kb_focus = NSWorkspace.sharedWorkspace.frontmostApplication;
然后一个窗口出现在顶部,长话短说:将文本放置在粘贴板上。覆盖窗口被破坏后,原始窗口将被重新激活并粘贴文本。
问题是在准备接收原始窗口之前粘贴文本:请参见Inject keyboard event into NSRunningApplication immediately after foregrounding it
一个丑陋的解决方案是使用计时器。
更漂亮的解决方案是将观察者附加到self.app_with_kb_focus
的{{1}}属性:
isactive
然后观察者将处理粘贴,并将其自身删除:
[self.app_with_kb_focus addobserver: self
forKeyPath: @"isactive"
options: 0
context: (void *)self.app_with_kb_focus ];
[textFieldWindow close];
// return previous foreground application to foreground
[self.app_with_kb_focus activateWithOptions: NSApplicationactivateAllWindows];
这通常可以正常工作,但偶尔会导致以下警告+崩溃:
2019-11-11 08:19:51.029956-0700 chi [40721:2568959]当观察者仍在向对象注册时,该对象将被释放。将来可能会崩溃。有人正在观察以下一个或多个属性:活动。
2019-11-11 08:19:51.030281-0700 chi [40721:2568959] [常规]释放了类NSRunningApplication的实例0x600002c42980,同时仍向其注册了键值观察器。当前观察信息: 上下文:0x600002c42980,属性:0x600000cec450> )
由于我无论如何都不会终止应用程序,这必须来自原始文件
- (void) observeValueForKeyPath: (NSString *) keyPath
ofObject: (id) object
change: (NSDictionary *) change
context: (void *) context
{
if( [keyPath isEqualToString: @"isactive"] )
{
NSRunningApplication* fg_app = (__bridge NSRunningApplication *)context;
[fg_app removeObserver: self
forKeyPath: @"isactive"];
paste( 0 );
}
...已在附加观察者后之后重新分配,但在观察者回调触发之前之前/没有。
因此,在此行之前,我想说:“如果有附加的观察者,请将其删除。”
如何用代码做到这一点?