如果NSTextView的物理窗口已满,则不会更新

时间:2014-02-02 04:36:47

标签: objective-c macos nstextview

我有一个NSTextView,我正在将其作为控制台。要记录内容,我使用以下方法:

- (void)log:(NSString *)logString
{
    NSDateFormatter* formatter = [[NSDateFormatter alloc] init];
    [formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
    NSString* dateTime = [formatter stringFromDate:[NSDate date]];

    [[self consoleText] setString:[NSString stringWithFormat:@"%@\n[%@]: %@", [self consoleText].string, dateTime, logString]];

}

此方法很有效,直到日志窗口变满。一旦滚动条出现,日志功能就会导致程序挂起。为什么呢?

编辑:

我添加了一些日志记录,发现导致程序挂起的确切行是:

[[self consoleText] setString:[NSString stringWithFormat:@"%@\n[%@]: %@", [self consoleText].string, dateTime, logString]];

特定问题来自于setString:方法本身。如果我将stringWithFormat:分开并声明字符串以预先设置它,它仍会挂起:

[[self consoleText] setString:outputString];

但仅当内容足够大才能产生滚动条时。

1 个答案:

答案 0 :(得分:0)

这里真正的问题是这个方法是从后台线程调用的。 AppKit在后台线程中不安全,因此您应该从主线程调用所有UI更新。将setString:置于主队列异步调度中可以解决问题:

dispatch_async(dispatch_get_main_queue(), ^(void){
    [[self consoleText] setString:outputString];
});

非常奇怪,直到需要出现滚动条才能正常工作......