NSTextView не обновляется в цикле во время записи на устройство USB - PullRequest
1 голос
/ 05 декабря 2008

Я пишу приложение Objective-C, которое связывается с USB-устройством. Приложение непрерывно записывает определенные данные на устройство и отображает состояние операции записи в textView, который является объектом NSTextView. Я вызываю метод -[NSTextView insertText:] в цикле, когда получаю состояние операции записи с устройства.

Проблема в том, что NSTextView не обновляется при каждом вызове -insertText:. Я получаю все содержимое NSTextView только после того, как весь цикл был выполнен.

Я не видел подходящего метода обновления или обновления для класса NSTextView. Как я могу получить статус операции и обновить NSTextView одновременно?

- (IBAction)notifyContentHasChanged:(NSInteger) block {
    NSString *str;
    str = [NSString stringWithFormat:@"Block Written Successfully: %d\n", block];
    [data insertText:str];
}

- (IBAction)func {
    while(USB_SUCCESS(status))
    {
        printf("\nBlocks Written Successfully: %d",BlockCnt);
        [refToSelf notifyContentHasChanged:BlockCnt];
    }
}

Обратите внимание, что printf на консоли обновляется своевременно, но не NSTextView.

Ответы [ 4 ]

4 голосов
/ 05 декабря 2008

Mac OS X не сбрасывает изменения в представлениях на экран сразу, чтобы избежать мерцания и разрывов, которые часто встречаются в таких ситуациях. Это означает, что вы не можете просто сидеть в цикле и выполнять операции блокировки во время обновления представления; если вы сделаете это, ни представление, ни что-либо еще в человеческом интерфейсе вашего приложения не обновится, и ваше приложение будет зависать и в итоге получит вращающийся курсор.

(Вращающийся курсор появляется, когда приложение не обменивается данными с оконным сервером в течение небольшого промежутка времени; нет никакого способа подавить это, по замыслу. приложение ушло в сорняки ", и вы должны стремиться к тому, чтобы оно никогда не появлялось у ваших пользователей.)

Чтобы управлять операциями блокировки в Какао, вы можете сделать одну из двух вещей:

  1. Вы можете выполнять операции блокировки в фоновом потоке и передавать результаты в основной поток для обновления вашего человеческого интерфейса. Например, вы можете осуществлять связь ввода-вывода или сокета таким образом, используя select(2) и стандартные вызовы ввода-вывода файлов UNIX.

  2. Вы можете запланировать операции в цикле выполнения (например, в главном цикле выполнения), если доступна совместимая версия; это обычно будет управлять фоновым потоком для блокирующей версии операции для вас. Например, NSFileHandle предоставляет совместимую с циклом выполнения абстракцию поверх файловых дескрипторов; NSStream делает это и для связи через сокеты.

1 голос
/ 21 апреля 2013

Вы должны использовать:

//Creates the background thread.
dispatch_queue_t backgroundQueue = dispatch_queue_create("Network", nil);

Для создания новой темы. Затем оберните ваш код в это:

//Runs code in background thread.
dispatch_async(backgroundQueue, ^(void){
    //Code Here.
});

И обновленный пользовательский интерфейс должен быть заключен в:

//Sends code within the background thread to the main thread.
dispatch_async(dispatch_get_main_queue(), ^(void){
    //Code Here.
});

Так в вашем коде:

- (IBAction)notifyContentHasChanged:(NSInteger) block {
    NSString *str;
    str = [NSString stringWithFormat:@"Block Written Successfully: %d\n", block];
    [data insertText:str];
}

- (IBAction)func {
    dispatch_queue_t backgroundQueue = dispatch_queue_create("Network", nil);
    dispatch_async(backgroundQueue, ^(void){
        while(USB_SUCCESS(status))
        {
            printf("\nBlocks Written Successfully: %d",BlockCnt);
            dispatch_async(dispatch_get_main_queue(), ^(void){
                [refToSelf notifyContentHasChanged:BlockCnt];
            });
        }
    });
}
0 голосов
/ 24 марта 2010

У меня есть цикл, который обращается к данным из сети и помещает их в БД. В процессе обработки я хотел бы иметь окно, похожее на консоль (а не в XCode, поскольку это будет скомпилированное приложение).

Итак, у меня есть NSTextView, который я изменяю textStorage и прокручиваю вниз до конца каждый раз через цикл. К сожалению, только видимые изменения происходят, когда цикл завершен (хотя и правильно).

Существует ли какой-то простой метод "ОК, обновите экран сейчас", не требуя низкого уровня или написания гораздо большего количества кода?

0 голосов
/ 06 декабря 2008

Вы должны иметь возможность обновить NSTextView с помощью -setNeedsDisplay: метод.

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