NSTextStorage ограничение на размер и частоту обновлений

Я пытаюсь создать приложение, подобное терминалу, которое может отображать журналы при запуске приложения.

Текущая реализация использует NSScrollView -> NSTextView. Тем не менее, я заметил, что размер NSTextView недостаточно велик для моей программы, и я не могу обновлять интерфейс очень часто.

Итак, предположим, у нас есть пример кода, подобный приведенному ниже (все остальное остается таким же, как у совершенно нового проекта Xcode APplication).

Программа продолжает выводить текстовый мусор в пользовательский интерфейс каждые 0,1 секунды и обновлять представление. Я обнаружил, что программа вылетает примерно через 4 минуты работы каждый раз. Также я должен добавить задержку 0,1 секунды между каждым текстом мусора. Если я не ставлю время задержки, программа сразу вылетает. Я хочу найти способы исправить это.

Я не уверен, что NSTextView по-прежнему является хорошим выбором для моего приложения. Если нет, может кто-нибудь указать мне правильное направление, то есть представление или набор представлений, которые могут вести себя как терминальное приложение.

Заранее спасибо.

#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

1 ответ

Решение

В общем, AppKit не является поточно-ориентированным. Вы изменяете текстовое хранилище и прокручиваете текстовое представление из фонового потока - поэтому неудивительно, что оно работает непоследовательно или вылетает.

Все, что вы продемонстрировали, это то, что вы используете AppKit неправильно, а не то, что NSTextView фатально испорчен для ваших целей. (Это все еще может быть смертельно опасным, но это не веская причина.)

Чтобы сделать этот тест правильно:

- (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];
}
Другие вопросы по тегам