NSView仅在断点上重绘

时间:2012-09-08 23:15:56

标签: objective-c macos cocoa

我在NSPopover内有自定义视图。它应该根据用户输入进行更改,并在用户第一次与其进行交互时进行更改,但无法重绘以下时间。

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

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

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

[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];中放置断点,每次更新视图时,此方法都会正常调用。如果相反,我让应用程序正常运行,第二次更新视图时,控制台中没有任何记录。如果我在NSLog方法中包含recalculateButtonLocations,则第二次没有记录任何内容,这意味着未调用该方法。

1 个答案:

答案 0 :(得分:0)

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

根据您绘制按钮的方式,最好使用layoutSubviewssetNeedsLayout,而不是drawRect来重新定位子视图。 [编辑:没有看到这是适用于Mac OS而不是iOS。 layout确实等同于layoutSubviews,setNeedsLayoutNSView,其中应进行子视图排列。]

如果没有更多信息,无法提供更多建议。但是,它与断点一起工作的事实很奇怪。我看不出为什么在方法调用行上有一个断点导致它被更频繁地调用的原因;应该调用或不调用该方法,无论是否有断点,并且看起来这个bug无法单独使用上面的代码进行复制......让我觉得它是代码中的其他因素导致了这个问题。


关于断点更改代码流的一些类似问题。也许睡觉代码/以断点以外的某种方式添加暂停,看看它是否有效?如果是这样,它可能表明以下问题之一。

  

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

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来自Breakpoint changes program flow

  

我之前见过这个,我的猜测是事件正在发生   发布太快,系统无法处理(因为它真的只有   例如,每秒处理20个关键事件。我猜是的   放入类似usleep(100000)的东西(暂停线程为1/10   一秒钟会有很大的帮助。

^ Dave DeLong来自CGKeyEvent Pasting working with Breakpoints, but not without

  

一般表示比赛条件;你的代码依赖于线程   在线程B击中一些之前完成或不完成某事   特别是。

来自EXC_BAD_ACCESS, but not when using breakpoints

^ bbum