简体   繁体   English

Cocoa REAL SLOW NSTextView。 有没有更好的方法将文本附加到NSTextView的内容?

[英]Cocoa REAL SLOW NSTextView. Is there a better way to append text to the contents of NSTextView?

I am very new to Cocoa and this is probably a complete newb question. 我对Cocoa很新,这可能是一个完整的新问题。 I am frustrated to death however. 然而,我对死亡感到沮丧。

I have an extremely simple Cocoa app (called "lines") to test sending 1000 lines of text to a text view. 我有一个非常简单的Cocoa应用程序(称为“行”)来测试向文本视图发送1000行文本。

I started in Xcode 4 with "new Cocoa project" with all the defaults. 我开始在Xcode 4中使用所有默认值的“新Cocoa项目”。 This gives a blank window object upon which I can drag IB UI elements. 这给出了一个空白窗口对象,我可以在其上拖动IB UI元素。

The UI I then constructed consists of a Text View and a button on the window of a NIB file. 我构建的UI包含一个文本视图和一个NIB文件窗口上的按钮。 I am using Xcode 4 to drag those two elements to the .h file. 我正在使用Xcode 4将这两个元素拖到.h文件中。 The text view is connected to outView and the "1000" button is connected to one_thousand_button method. 文本视图连接到outView ,“1000”按钮连接到one_thousand_button方法。

用户界面

Clicking the button "1000" triggers a loop to print 1,000 lines of text ("line 1\\n" "line 2\\n" ... "line 1000") to the NSTextView called "outView" 单击“1000”按钮会触发一个循环,将1000行文本(“第1行\\ n”“第2行\\ n”......“第1000行”)打印到名为“outView”的NSTextView

Here is the entire code (other than the .XIB file described): 这是整个代码(除了描述的.XIB文件):

linesAppDelegate.h: linesAppDelegate.h:

#import <Cocoa/Cocoa.h>

@interface linesAppDelegate : NSObject <NSApplicationDelegate> {
@private
    NSWindow *window;
    NSTextView *outView;
}

@property (assign) IBOutlet NSWindow *window;
@property (assign) IBOutlet NSTextView *outView;
- (IBAction)one_thousand_button:(id)sender;

@end

linesAppDelegate.m: linesAppDelegate.m:

#import "linesAppDelegate.h"

@implementation linesAppDelegate

@synthesize window;
@synthesize outView;

- (IBAction)one_thousand_button:(id)sender {
    NSString* oldString;
    NSString* newString;

    for(int i=1; i<=1000; i++){
        oldString = [outView string];
        newString = [oldString stringByAppendingString: 
                     [NSString stringWithFormat: @"Line %i\n",i]];
        [outView setString: newString];    
    }
}
@end

This is REALLY SLOW to execute. 执行起来非常慢。 Perhaps 7 seconds the first time and increasingly slow with each press of "1000". 也许是第一次7秒,每次按“1000”时越来越慢。 Even has the spinning colorful pizza of death! 甚至还有旋转的彩色披萨!

I realize that this is probably not the right way to fill a NSTextView with 1,000 lines of text and that the loop that read the contents of the text view and appends that with stringByAppendingString method is the bottleneck. 我意识到这可能不是用1000行文本填充NSTextView的正确方法,并且读取文本视图内容并使用stringByAppendingString方法附加的stringByAppendingString是瓶颈。

What is the alternative method however? 然而,另一种方法是什么?

Result 结果

I wrapped this code: 我包装了这段代码:

    mach_timebase_info_data_t info;
    mach_timebase_info(&info);
    uint64_t start = mach_absolute_time();

// timed code    

    uint64_t duration = mach_absolute_time() - start;
    duration *= info.numer;
    duration /= info.denom;
    duration /= 1000000;

    NSLog(@"timed code took %lld milliseconds!", duration);

around the code from Adam Preble , my original, and drewk : 围绕Adam Preble ,我的原创和drewk的代码

                 Adam Preble  (Adam, base)     drewk    my pitiful code
 1st run:           3ms          269ms         260ms      1,950ms
 2nd run            3ms          269ms         250ms      2,332ms
 3rd run:           2ms          270ms         260ms      2,880ms

The first run adds 1,000 lines; 第一轮比赛增加了1,000行; 2nd run adds another 1,000 lines, etc. (Adam, base) is his code without the beginEditing and endEditing 第二次运行添加另外1,000行等(Adam,base)是他的代码,没有beginEditingendEditing

It is clear that using beginEditing and endEditing is WAY faster! 很明显,使用beginEditingendEditing更快!

See the Apple documents on Synchronizing Editing . 请参阅有关同步编辑的Apple文档。

Wrap your updates to the text storage in calls to beginEditing and endEditing . 在对beginEditingendEditing调用beginEditing更新包装到文本存储中。 This causes Cocoa to hold all of its change notifications until you have finished making your changes to the text storage. 这会导致Cocoa保留所有更改通知,直到您完成对文本存储的更改。

- (IBAction)oneThousandButton:(id)sender
{
    NSTextStorage *textStorage = [outView textStorage];
    [textStorage beginEditing];
    for (int i = 1; i <= 1000; i++)
    {
        NSString *line = [NSString stringWithFormat: @"Line %i\n", i];
        [textStorage replaceCharactersInRange:NSMakeRange([textStorage length], 0)
                                   withString:line];
    }
    [textStorage endEditing];
}

On my system the above action runs in about 10ms. 在我的系统上,上述操作大约需要10毫秒。 If I comment out the calls to beginEditing / endEditing , it takes about 470ms. 如果我注释掉对beginEditing / endEditing的调用,则需要大约470ms。

Try this: 尝试这个:

- (IBAction)one_thousand_button:(id)sender {

    for(int i=1; i<=1000; i++){      
         [[[outView textStorage] mutableString] appendString: 
                    [NSString stringWithFormat: @"Line %i\n",i]];
    }
}

There is an invaluable "quickie" reference to Objective-C HERE with NSTextView covered HERE. 这里有一个非常有用的“quickie”参考Objective-C HERE和NSTextView

Best... 最好...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM