В Какао, почему текстовое поле не будет отображаться до тех пор, пока IBAction не будет полностью выполнен? - PullRequest
0 голосов
/ 04 мая 2010

У меня есть IBAction с некоторым простым кодом внутри:

-(IBAction)change:(id)sender {
    [textfield setHidden:NO];
    [self dolengthyaction];
}

'textfield' - это NSTextField в nib-файле, а -'dolengthyaction - это функция, выполнение которой занимает около минуты.

Мой вопрос: почему текстовое поле не отображается, пока не будет выполнено ПОСЛЕ «dolengthyaction»?Я хочу, чтобы это было раскрыто до того, как начнется длительная акция.Это врожденная проблема или что-то не так с моим кодом?(или в другой части моего кода?)

Я все еще не очень хорош в программировании, поэтому я извиняюсь, если что-то написал плохо и отформатировал что-то неправильно.

РЕДАКТИРОВАТЬ: Там нетмногое другое, кроме этого IBAction и -dolengthyaction ...

-(void)doLengthyAction {
    sleep(10);
}
-(IBAction)change:(id)sender {
    [textfield setHidden:NO];
    [self doLengthyAction];
    [textfield setHidden:YES];
}

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

По сути, это означает, что сейчас он вообще не отображается.

На самом деле, в -doLengthyAction это не sleep (10), а операция NSFileManager, которая копирует около 50 МБ материала.,Код был довольно длинным, но если вы хотите, чтобы я опубликовал его, я могу.Я проверил это с помощью sleep (), но он тоже не работает.

Ответы [ 6 ]

6 голосов
/ 04 мая 2010

Все операции рисования (включая скрытие и отображение видов) запускаются из цикла выполнения. Цикл выполнения не может выполнить следующее событие, пока ваша функция не вернется.

Если у вас есть операция, выполнение которой занимает более секунды, вы должны выполнить ее в потоке. Как только он завершится, используйте executeSelectorOnMainThread, чтобы внести изменения в пользовательский интерфейс в основном потоке.

5 голосов
/ 04 мая 2010

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

Вы действительно должны обрабатывать вещив фоновом потоке, если они будут работать долго.Если вы этого не сделаете, пользовательский интерфейс будет играть в мяч во время выполнения вашей операции.

Если вы нацеливаетесь на 10.6+, вы можете использовать GCD и блоки, как указано ниже, чтобы легко выполнять задачи в фоновом режиме (и не нужно определятьнесколько методов для достижения цели):

-(void)doLengthyAction {
    sleep(10);
}
-(IBAction)change:(id)sender {
    [textfield setHidden:NO];
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [self doLengthyAction];
        dispatch_async(dispatch_get_main_queue(), ^{
            [textfield setHidden:YES];
        });
    });
}

Конечно, используя это, вы должны быть уверены, что то, что происходит в длительном действии, является поточно-ориентированным, но в итоге вы получителучший пользовательский опыт.Для получения дополнительной информации об этом типе кода CGD, вы можете прочитать это .

1 голос
/ 04 мая 2010
-(void)doLengthyAction {
     sleep(10);
    [textfield setHidden:YES];
} 

-(IBAction)change:(id)sender {
    [textfield setHidden:NO];
    [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(doLengthyAction) userInfo:nil repeats:NO];
}
1 голос
/ 04 мая 2010

Не могу сказать, что именно происходит, не глядя на остальную часть кода, но хакерский способ - попробовать:

-(IBAction)change:(id)sender {
   [textfield setHidden:NO];
   [self performSelector:@selector(doLenghtyAction) withObject:nil afterDelay:0.1]; --> or maybe even 0.0
 }
1 голос
/ 04 мая 2010

Я думаю, что-то не так с остальной частью вашего кода. Этого не должно быть.

Опубликовать больше?

0 голосов
/ 04 мая 2010

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

-(IBAction)change:(id)sender {
    [textfield setHidden:NO];
    [[textfield window] display]; // force the window to update
    [self doLengthyAction];
    [textfield setHidden:YES];
}
...