可可/核心动画:所有东西都跳转到becomeFirstResponder()

时间:2016-06-13 00:32:15

标签: macos cocoa core-animation nstextfield

要点:我有一堆嵌套在一个MainView中的观点。当我在其中一个视图中嵌套的becomeFirstResponder()上致电NSTextField时,MainView内的每个视图突然跳转到半任意的旧位置。

实际原因可能是许多事情中的任何一个,其中可能是我只写了一个星期的Cocoa。

这是实际结构:

MainView: NSView
 ├ ContactTile: NSView (layer-backed)
 |  └ /* several CALayers */
 ├ ContactTile
 ├ …
 ├ ContactTile
 └ StatusTile: NSView (layer-backed)
    ├ SearchIcon: NSView (layer-backed)
    |  └ SearchIconLayer: CALayer
    └ NSTextField

我使用ReactiveCocoa支持所有核心业务逻辑,异步调度回主UI线程以进行与绘图相关的操作。

StatusTile初始化并在创建MainView时立即添加为子视图,其位置设置为屏幕的右上角区域。 ContactTiles是动态创建和添加的 - 创建和子视图添加发生在一个ReactiveCocoa观察者中(使初始位置保持为(0, 0)),并在另一个"重新布局"观察者所有ContactTile以及StatusTile都是动画的,并且定位的代码看起来大致如下:

let anim = CABasicAnimation.init(keyPath: "position");
let (from, to) = /* bunch of positional calculation */;
anim.fromValue = NSValue.init(point: from);
anim.toValue = NSValue.init(point: to);

tile.layer!.removeAnimation("contacttile-layout");
tile.layer!.addAnimation(anim, forKey: "contacttile-layout");
tile.layer!.position = to;

只要我不与becomeFirstResponder做任何事情,这一切都能很好地发挥作用;瓷砖从预期位置生成动画,并按预期保持在那里。如果我在他们的.position办理登机手续,他们就会完全符合我的期望。

但现在我添加代码,在单独的ReactiveCocoa观察器中侦听全局热键。该全局热键信号同时触发重新布局,导致您看到的动画/布局代码。但它也会触发一个单独的观察者,在上面的textField.becomeFirstResponder()视图中调用StatusTile

GlobalInteraction.sharedInstance.activated.observeNext { activated in
    if activated {
        dispatch_async(dispatch_get_main_queue(), { self._searchField.becomeFirstResponder(); });
    } else {
        self._searchField.stringValue = "";
    }
}

现在发生的事情是动画完全按照预期进行,但是在动画完成时,每个元素重置到其初始位置,如前几段所述:StatusTile恢复到其初始右上角位置,并且每个ContactTile都会恢复为(0, 0)

如果我检查他们实际的.position静止状态,他们确实会报告(0, 0)。但如果我在上面的计算块之后立即检查他们的.position,那么一切都是我期望的。甚至更奇怪的是,.becomeFirstResponder()调用非常一致地发生之前我执行上面的重新布局动画设置。因此,就我的代码而言,无论如何,在之后,我的位置的调用都会被说明并完成。

当随后发生更改布局的内容时,例如在文本字段或其他外部输入中键入内容,即使文本字段具有焦点,所有内容也会恢复正常工作。只有在最初激活时,一切都会反弹。

一些可能相关的怪癖:

  • 我渲染到一个透明的无边框窗口,所以一切都漂浮在太空中。
  • 应用程序通常将焦点作为同一个全局热键的一部分。
  • ?不知道还有什么,但它是一种奇怪的应用程序,我是Cocoa的新手,所以请问你是否有澄清问题。

0 个答案:

没有答案