Objective c 如果NSTextView';s的物理窗口满了,它赢了';t更新
我有一个NSTextView,它的功能是作为控制台。要记录内容,我使用以下方法:Objective c 如果NSTextView';s的物理窗口满了,它赢了';t更新,objective-c,macos,nstextview,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 stringFr
- (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]];
}
在日志窗口满之前,此方法非常有效。滚动条一出现,log函数就会使程序挂起。为什么?
编辑:
我添加了一些日志记录,发现导致程序挂起的确切行是:
[[self consoleText] setString:[NSString stringWithFormat:@"%@\n[%@]: %@", [self consoleText].string, dateTime, logString]];
特定的问题是由它自身的setString:
方法引起的。如果我将stringWithFormat:
分开,并声明要预先设置的字符串,它仍然挂起:
[[self consoleText] setString:outputString];
但是,只有当内容足够大以致于产生一个滚动条时。这里真正的问题是这个方法是从后台线程调用的。AppKit在后台线程中不安全,因此您应该从主线程调用所有UI更新。将
setString:
放置在主队列异步调度中修复了以下问题:
dispatch_async(dispatch_get_main_queue(), ^(void){
[[self consoleText] setString:outputString];
});
奇怪的是,在需要出现滚动条之前,它工作得很好