Текст UILabel не обновляется
Я не могу изменить текст UILabel. Код для UILabel внутри viewDidLoad:
startLabel=[[UILabel alloc] initWithFrame:CGRectMake(75, 395, 200, 30)];
[email protected]"Recording Sound ...";
startLabel.backgroundColor=[UIColor clearColor];
startLabel.textColor=[UIColor whiteColor];
startLabel.font=[UIFont boldSystemFontOfSize:17];
[self.view addSubview:startLabel];
Позже, если я хочу изменить метку текста со следующим кодом, он не изменяется в приложении:
[email protected]"Searching Database ...";
или
[startLabel setText:@"Searching Database ..."];
UILabel не пуст, я распечатал его во время отладки, и он показывает:
(gdb) po startLabel
<UILabel: 0x2c1a30; frame = (75 395; 200 30); text = 'Searching Database ...';
clipsToBounds = YES; userInteractionEnabled = NO; layer = <CALayer: 0x2ae8f0>>
Итак, текст метки изменяется внутри UILabel, но не обновляется на экране.
Может кто-нибудь любезно сообщить мне, что
Мне здесь не хватает? Спасибо.
Изменить 1: Я пробовал performSelectorOnMainThread:
- не работал у меня.
Изменить 2: Я использую классы AVFoundation
и ASIHTTP
для записи звука и загрузки записанного файла здесь. Ничего больше. Не использовал нить.
Ответы
Ответ 1
Возможно, вы столкнулись с проблемой потоковой передачи, упомянутой в комментариях выше. Если у вас есть метод, который работает в основном потоке и выполняет некоторые действия (например, поиск в базе данных), обновления, которые вы вносите в пользовательский интерфейс, не будут выполняться до тех пор, пока цикл выполнения не получит контроль. Итак, если у вас есть долгая, трудоемкая задача, идущая в основном потоке, запустите этот код после установки текста метки:
- (void)doSomethingTimeConsuming
... consume some time ...
... set text of label ...
[[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.5]];
... continue long operation ...
}
Это должно скрыть любые изменения пользовательского интерфейса, которые вы сделали. Хотя это может быть разумным и функциональным взломом, он не превзойдет альтернативы. Я настоятельно рекомендую вам выполнять ваши задачи, требующие много времени, в фоновом потоке и обновлять интерфейс через основной поток с помощью performSelectorOnMainThread:withObject:waitUntilDone:
. См. Страницу Apple в Управление потоками iOS.
Ответ 2
В моем случае функция, которая была обновлена, вызывалась из сенсорного распознавателя в потоке, но место в функции, где я меняю значение свойства текста метки, я возвращаю его в основной поток:
dispatch_async(dispatch_get_main_queue(), ^{
[self.someLabel setText:someString];
});
Ответ 3
Моя немного более неожиданная, хотя и разумная - просто не то, о чем кто-то слишком сильно думает.
Я должен обновить UILabel
, когда получаю NSNotification
, который я запускал где-то в другом месте. Однако уведомление было уволено из фонового потока, поэтому даже методы прослушивателя, которые обновляют текст ярлыков, запускаются в фоновом режиме.
Если вы полагаетесь на NSNotification
, чтобы обновить ярлык или любое ваше представление, выполните огонь NSNotification
из основного потока пользовательского интерфейса.
Ответ 4
У меня был UILabel, показывающий номер уровня, который не обновлялся бы до нового уровня на UIViewController. Единственное жизнеспособное решение, которое я смог найти, заключалось в том, чтобы вызвать setNeedsDisplay в основном потоке контроллера вида, который владел UILabel
-(void)changeLevelLabel:(int)theLevel {
dispatch_async(dispatch_get_main_queue(), ^{
self.levelLabel.text = [NSString stringWithFormat:@"%d",theLevel];
[self.levelLabel setNeedsDisplay];
});
}
Подробнее см. http://iosdevelopmentjournal.com/blog/2013/01/16/forcing-things-to-run-on-the-main-thread/