NSTextField ждет, пока конец цикла не будет обновлен

Вот проблема: у меня есть код, который выглядит так

otherWinController = [[NotificationWindowController alloc] init]; for (int i = 0; i < 10; i++) { [otherWinController showMessage:[NSString stringWithFormat:@"%d", i]]; NSLog(@"%d", i); sleep(1); } 

где otherWinController является подclassом NSWindowController, который я использую для обновления моего windows, поскольку изменения происходят в коде, а метод init init просто открывает апплет и показывает окно. showMessage – это метод, который изменяет NSTextView для отображения любого текста в параметре.

в NSLog, текст меняется каждую секунду и составляет всего десять. Однако для метода showMessage текст пуст в течение полных десяти секунд, а затем просто отображает номер 10. любые мысли?

FTR метод showMessage просто

 - (void)showMessage:(NSString *)text { [[self message] setStringValue:text]; } 

не то, что это должно иметь значение, это довольно просто.

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

 [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow: 0.1]]; 

Проблема в том, что вы блокируете основной stream в вашем цикле for и обновления пользовательского интерфейса происходят в основном streamе. Цикл запуска основного streamа будет только вращаться (и, следовательно, обновления пользовательского интерфейса будут иметь место) после того, как метод, содержащий цикл завершения цикла.

Если вы хотите обновлять это текстовое поле каждую секунду, вы должны использовать таймер. Например, учитывая, что otherWinController является переменной экземпляра, объявите свойство counter в своем classе и:

 otherWinController = [[NotificationWindowController alloc] init]; self.counter = 0; [otherWinController showMessage:[NSString stringWithFormat:@"%d", self.counter]]; [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateCounter:) userInfo:nil repeats:YES]; 

В том же classе реализуйте метод, который вызывается всякий раз, когда время уволено:

 - (void)updateCounter:(NSTimer *)timer { self.counter = self.counter + 1; [otherWinController showMessage:[NSString stringWithFormat:@"%d", self.counter]]; if (self.counter == 9) { [timer invalidate]; // if you want to reset the counter, // self.counter = 0; } } 

Представления не обновляются до конца цикла выполнения ; ваш цикл for не позволяет циклу запуска продолжать, поэтому все сделанные вами обновления вида выполняются только после завершения цикла for.

Вы должны либо использовать NSTimer либо performSelector:withObject:afterDelay: изменить отображение в виде петли.

 [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(changeTextFieldsString:) userInfo:nil repeats:YES]; 

Тогда действие вашего таймера изменит изображение вида:

 - (void)changeTextFieldsString:(NSTimer *)tim { // currStringIdx is an ivar keeping track of our position if( currStringIdx >= maxStringIdx ){ [tim invalidate]; return; } [otherWinController showMessage:[NSString stringWithFormat:@"%d", currStringIdx]] currStringIdx++; } 

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

Я думаю, что, вызывая sleep (1), вы блокируете основной stream, который должен нарисовать ваши изменения. Поэтому дисплей не обновляется. Диспетчер задач не будет прерывать вашу функцию. В этом случае вы не должны использовать сон . Пожалуйста, взгляните на class NSTimer . Он имеет статический метод scheduleTimerWithTimeInterval , который вы должны использовать.

 static UIViewController *controller = nil; ..... { ..... otherWinController = [[NotificationWindowController alloc] init]; controller = otherWinController; [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(timerTick:) userInfo:nil repeats:YES]; //set timer with one second interval ..... } - (void) timerTick:(NSTimer*)theTimer { static int i = 0; [controller showMessage:[NSString stringWithFormat:@"%d", i]]; NSLog(@"%d", i); if (++i == 10) { [theTimer invalidate]; i = 0; } } 
  • Как ограничить длину текста NSTextField и сохранить его всегда в верхнем регистре?
  • Почему моя слабая ссылка не устранена сразу после того, как сильные исчезли?
  • Objective-C - CABasicAnimation, применяющая изменения после анимации?
  • Что такое аргумент BOOL * stop для enumerateObjectsUsingBlock: используется для?
  • Возможно ли обновить один UITableViewCell в UITableView?
  • Удаленное уведомление iOS 8
  • registerForRemoteNotificationTypes: не поддерживается в iOS 8.0 и более поздних версиях
  • objective C: что такое «(id) отправитель»?
  • Верхние индексы в атрибутной строке
  • В чем разница между наследованием и категориями в Objective-C
  • Индекс символов в точке касания для UILabel
  • Давайте будем гением компьютера.