0

我在NSPopover. 它应该根据用户输入进行更改,并且它会在用户第一次与之交互时进行,但在以下时间重绘失败。

我试图NSLog在方法内部放置一个-drawRect:,但在正常执行期间它不会被调用。当我尝试调试并在方法中放置断点时,它会正常调用并且应用程序可以正常工作。

-setNeedsDisplay:每次需要重绘时,我都会显式调用视图方法。我不明白为什么它应该有所作为。

这是更新视图状态的代码。这些方法是NSTextField委托方法的一部分,-textDidChange:我检查了每次用户在与弹出框关联的文本字段中键入内容时都会调用这些方法。

[tokenCloud tokensToHighlight:[NSArray arrayWithObject:completeSuggestionString]];
tokenCloud.tokens = filteredTokens;
[tokenCloud setNeedsDisplay:YES];

视图是一系列凹进的按钮。第一行更新弹出框中所有按钮的状态,第二行更新添加或删除按钮。它们都可以正常工作,因为第一次调用视图时会正确更新。我还检查了按钮的状态tokenCloud及其属性tokens是否正确更新。问题是NSView子类tokenCloud不会重绘,因此更改不会第二次反映在 UI 中。

这是视图的绘制方法:

- (void)drawRect:(NSRect)rect {
    [self recalculateButtonLocations];
    NSLog(@"Redrawn");
}

如果我在[self recalculateButtonLocations];. 相反,如果我让应用程序正常运行,那么在我第二次更新视图时,控制台中不会记录任何内容。如果我NSLogrecalculateButtonLocations方法中包含同样的事情,第二次没有记录任何内容,这意味着没有调用该方法。

4

1 回答 1

0

EDIT2:对于未来的读者,很抱歉这个答案质量低下。其中大部分是无用的,有用的部分应该作为评论。我会删除它,但我觉得那是不诚实的。希望任何有这个问题的人都可以在链接的答案中找到更多的见解,其中确实包含一些关于为什么有时添加断点会改变程序流程的信息。

根据您绘制按钮的方式,使用layoutSubviewsand可能setNeedsLayoutdrawRect重新定位子视图更好。[编辑:没有看到这是针对 Mac OS 而不是 iOS。layout确实相当于 layoutSubviews 并且有一个setNeedsLayoutfor NSView,应该在其中进行子视图排列。]

如果没有更多信息,无法提供更多建议。然而,它与断点一起工作的事实很奇怪。我看不出为什么在方法调用行上设置断点会导致它被更频繁地调用。无论是否有断点,都应该调用该方法,并且似乎无法仅使用上述代码复制此错误...使我认为这是您的代码中的其他内容导致了此问题。


关于断点更改代码流的一些类似问题。也许以断点以外的方式休眠代码/添加暂停,看看它是否有效?如果确实如此,则可能表明存在以下问题之一。

断点改变代码工作方式的第一大原因是竞争条件。它基本上是这样的:

Without breakpoints:
    make some asynchronous request
    do something with response
    ERROR because request hasn't responded yet

With breakpoints:
    send some asynchronous request
    wait for user to continue
    response arrived while waiting for the continue
    do something with response
    OK!

^Niet the Dark Absol from Breakpoint 改变程序流程

我以前见过这种情况,我的猜测是事件发布得太快,系统无法处理(因为它实际上只需要处理不超过每秒 20 个关键事件)。我猜想加入类似 usleep(100000) 的东西(将线程暂停 1/10 秒)会有很大帮助。

^来自CGKeyEvent Pasting 的 Dave DeLong 使用断点,但并非没有

一般表示竞态条件;您的代码取决于线程 A 在线程 B 达到某个特定状态之前是否完成某些事情。

^bbum 来自EXC_BAD_ACCESS,但不是在使用断点时

于 2012-09-09T02:11:16.957 回答