NSTextStorage limitation on size and frequency of updates

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

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 Exit Code 1 - Duplicate Symbol
  • How to add the parent path to RealmSwift.framework in the “Framework Search Paths” section?
  • Unable to modify array in Singleton
  • How can i find memory location from apple crash report? from where my app is crash.?
  • Converting UIImageView to UIImage
  • Anyone used libvlc on Mac?
  • So let’s say we have a sample code like this below, (everything else stays the same as a brand new Xcode APplication project).

    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.

    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.

    Thanks in advance.

    #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
    

    Solutions Collect From Internet About “NSTextStorage limitation on size and frequency of updates”

    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.

    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];
    }