Какао на самом деле медленный NSTextView.Есть ли лучший способ добавить текст к содержимому NSTextView? - PullRequest
6 голосов
/ 31 марта 2011

Я очень новичок в Какао, и это, вероятно, полный новый вопрос.Я расстроен до смерти как бы то ни было.

У меня есть чрезвычайно простое приложение Cocoa (называемое «линиями»), чтобы проверить отправку 1000 строк текста в текстовое представление.

Я начал в Xcode 4 с «нового проекта Какао» со всеми настройками по умолчанию.Это дает пустой объект окна, на котором я могу перетаскивать элементы пользовательского интерфейса IB.

Пользовательский интерфейс, который я тогда создал, состоит из текстового представления и кнопки в окне файла NIB.Я использую Xcode 4, чтобы перетащить эти два элемента в файл .h.Просмотр текста связан с outView, а кнопка «1000» связана с методом one_thousand_button.

The UI

Нажатие кнопки «1000» запускает цикл для печати 1000 строк текста («строка 1 \ n», «строка 2 \ n» ... «строка 1000»)) в NSTextView с именем «outView»

Вот весь код (кроме описанного файла .XIB):

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:

#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

Это действительно МЕДЛЕННО выполнить.Возможно, 7 секунд в первый раз и все медленнее с каждым нажатием «1000».Даже есть вращающаяся красочная пицца смерти!

Я понимаю, что это, вероятно, не правильный способ заполнить NSTextView 1000 строк текста и что цикл, который читает содержимое текстового представления и добавляет это сstringByAppendingString метод является узким местом.

Каков же альтернативный метод?

Результат

Я обернул этот код:

    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);

вокруг кода из Адам Пребл , мой оригинал, и 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

Первый запуск добавляет 1000 строк;2-й прогон добавляет еще 1000 строк и т. Д. (Адам, база) - это его код без beginEditing и endEditing

Очевидно, что использование beginEditing и endEditing ПУТЬ быстрее!

См. Документы Apple по Синхронизация редактирования .

Ответы [ 2 ]

16 голосов
/ 31 марта 2011

Оберните ваши обновления в хранилище текста в вызовах на beginEditing и endEditing.Это заставляет 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];
}

В моей системе вышеуказанное действие выполняется примерно за 10 мс.Если я закомментирую вызовы на beginEditing / endEditing, это займет около 470 мс.

3 голосов
/ 31 марта 2011

Попробуйте это:

- (IBAction)one_thousand_button:(id)sender {

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

Имеется неоценимая ссылка на Objective-C ЗДЕСЬ с покрытием NSTextView ЗДЕСЬ.

Лучший ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...