NSTextStorage对大小和更新频率的限制 [英] NSTextStorage limitation on size and frequency of updates

查看:100
本文介绍了NSTextStorage对大小和更新频率的限制的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建一个类似终端的应用程序,该应用程序在运行时可以显示日志.

I am trying to create a Terminal like application that can display logs when application is running.

当前实现使用NSScrollView-> NSTextView.但是,我注意到NSTextView的大小不足以容纳我的程序,因此我不能非常频繁地更新UI.

Current implementation uses NSScrollView -> NSTextView. However, I notice that the size of the NSTextView is not large enough for my program and I can not update the UI very frequently.

因此,我们假设下面有一个示例代码(其他所有内容都与全新的Xcode APplication项目相同).

So let's say we have a sample code like this below, (everything else stays the same as a brand new Xcode APplication project).

程序继续每隔0.1秒将一些垃圾文本打印到UI并更新视图.我发现程序每次运行约4分钟后就会崩溃.我也必须在每个垃圾文本之间添加0.1秒的延迟.如果我没有延迟,程序将立即崩溃.我想找到解决此问题的方法.

The program continues to print some garbage text to the UI every 0.1 second and update the view. I found the program crashes after about 4 minutes of running every time. Also i have to add a 0.1 second delay between each garbage text. If i didn't put any time of delay, the program crashes right away. I want to find ways to fix this.

我不确定NSTextView是否仍然是我的应用程序的不错选择.如果没有,那么谁能指出我的正确方向,即该视图或视图集合的行为可以像终端应用程序一样.

I am not sure if NSTextView is still the good choice of my application. If not, can anyone point me to the right direction, which view or collection of views that can behave like a Terminal Application.

谢谢.

#import "AppDelegate.h"

@implementation AppDelegate

@synthesize window = _window;
@synthesize queue = _queue;
@synthesize theTextView = _theTextView;

- (void)dealloc
{
    [super dealloc];
}

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    // Insert code here to initialize your application 322, 40, 895, 720
    NSScrollView *scrollview = [[NSScrollView alloc]
                                initWithFrame:[[_window contentView] frame]];
    NSSize contentSize = [scrollview contentSize];

    [scrollview setBorderType:NSNoBorder];
    [scrollview setHasVerticalScroller:YES];
    [scrollview setHasHorizontalScroller:NO];
    [scrollview setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];

    _theTextView = [[NSTextView alloc] initWithFrame:NSMakeRect(0, 0,
                                                               contentSize.width, contentSize.height)];
    [_theTextView setMinSize:NSMakeSize(0.0, contentSize.height)];
    [_theTextView setMaxSize:NSMakeSize(FLT_MAX, FLT_MAX)];
    [_theTextView setVerticallyResizable:YES];
    [_theTextView setHorizontallyResizable:NO];
    [_theTextView setAutoresizingMask:NSViewWidthSizable];

    [[_theTextView textContainer] setContainerSize:NSMakeSize(contentSize.width, FLT_MAX)];
    [[_theTextView textContainer] setWidthTracksTextView:YES];

    [scrollview setDocumentView:_theTextView];
    [_window setContentView:scrollview];
    [_window makeKeyAndOrderFront:nil];
    [_window makeFirstResponder:_theTextView];

    [[_theTextView enclosingScrollView] setHasHorizontalScroller:YES];
    [_theTextView setHorizontallyResizable:YES];
    [_theTextView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
    [[_theTextView textContainer] setContainerSize:NSMakeSize(FLT_MAX, FLT_MAX)];
    [[_theTextView textContainer] setWidthTracksTextView:NO];
    _queue = dispatch_queue_create("com.example.MyQueue", NULL);

    [self start];
}

- (void) start {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
        [self feed];
    });

}
- (void) feed {
    while (1) {
        dispatch_async(_queue, ^(void){
            NSString * displaytext = (NSString *) CFSTR("Testing Line - asdfasdfklqjwer;opfjiasdlk;fjasd\n");

            NSAttributedString *string = [[NSAttributedString alloc] initWithString:displaytext];
            NSLog(@"Output is %@", string);

            //        [[_theTextView textStorage] appendAttributedString:string];

            [[_theTextView textStorage] beginEditing];
            [[_theTextView textStorage] appendAttributedString:string];
            [[_theTextView textStorage] endEditing];
            [_theTextView scrollRangeToVisible:NSMakeRange([[_theTextView string] length], 0)];

            [string release];

        });
        usleep(100000);
    }

}

@end

推荐答案

AppKit通常不是线程安全的.您正在从后台线程更改文本存储并滚动文本视图-因此,它不一致地工作或崩溃都就不足为奇了.

AppKit is not, in general, thread safe. You're changing the text storage, and scrolling the text view, from a background thread -- so it's no surprise that it works inconsistently or crashes.

所有显示的都是您使用的AppKit错误,而不是NSTextView出于您的目的而存在致命缺陷. (它可能仍然存在致命缺陷,但这不是一个很好的理由.)

All you've demonstrated is that you're using AppKit incorrectly, not that NSTextView is fatally flawed for your purposes. (It might still be fatally flawed, but this isn't a good reason.)

要正确执行此测试,请执行以下操作:

To do this test correctly:

- (void)start
{
    [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(feedOne:) userInfo:nil repeats:YES];
}

- (void)feedOne:(NSTimer*)timer
{
    NSString* displaytext = @"Testing Line - asdfasdfklqjwer;opfjiasdlk;fjasd\n";    
    NSAttributedString* string = [[NSAttributedString alloc] initWithString:displaytext];

    [[_theTextView textStorage] beginEditing];
    [[_theTextView textStorage] appendAttributedString:string];
    [[_theTextView textStorage] endEditing];
    [_theTextView scrollRangeToVisible:NSMakeRange([[_theTextView string] length], 0)];

    [string release];
}

这篇关于NSTextStorage对大小和更新频率的限制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆