Ответ 1
Мигание не вызвано таймером как таковым. Метод UIButton setTitle: forState вызывает мигание. Одна простая работа - использовать UIButton без названия и накладывать UILabel. Когда вы меняете текст UILabel, он не будет мигать.
Когда я вызываю setTitle на UIButton, кнопка мигает в iOS 7. Я попробовал установить myButton.highlighted = NO, но это не остановило кнопку от мигания.
[myButton setTitle:[[NSUserDefaults standardUserDefaults] stringForKey:@"elapsedLabelKey"] forState:UIControlStateNormal];
myButton.highlighted = NO;
Вот как я настроил таймер, который обновил названия:
- (void)actionTimer {
if (myTimer == nil) {
myTimer = [NSTimer scheduledTimerWithTimeInterval: 1.0
target: self
selector: @selector(showActivity)
userInfo: nil
repeats: YES];
}
}
Вот метод, который фактически обновляет названия:
- (void)showActivity {
NSString *sym = [[NSLocale currentLocale] objectForKey:NSLocaleCurrencySymbol];
if (pauseInterval == nil) {
// Update clock
seconds = [[NSDate date] timeIntervalSinceDate:startInterval] - breakTime;
// Update total earned
secRate = rate.value / 60 / 60;
total = secRate * seconds;
[totalLabel setTitle:[NSString stringWithFormat:@"%@%.4f",sym,total] forState:UIControlStateNormal];
days = seconds / (60 * 60 * 24);
seconds -= days * (60 * 60 * 24);
int hours = seconds / (60 * 60);
fhours = (float)seconds / (60.0 * 60.0);
seconds -= hours * (60 * 60);
int minutes = seconds / 60;
seconds -= minutes * 60;
// Update the timer clock
[elapsed setTitle:[NSString stringWithFormat:@"%.2i:%.2i:%.2i:%.2i",days,hours,minutes,seconds] forState:UIControlStateNormal];
}
}
Мигание не вызвано таймером как таковым. Метод UIButton setTitle: forState вызывает мигание. Одна простая работа - использовать UIButton без названия и накладывать UILabel. Когда вы меняете текст UILabel, он не будет мигать.
Установите тип кнопки UIButtonTypeCustom, и он перестанет мигать
Лучшим подходом, чем [UIView setAnimationsEnabled:NO]
который может повлиять на другие анимации, является отключение только анимации конкретного заголовка.
Objective-C:
[UIView performWithoutAnimation:^{
[myButton setTitle:text forState:UIControlStateNormal];
[myButton layoutIfNeeded];
}];
Swift:
UIView.performWithoutAnimation {
myButton.setTitle(text, for: .normal)
myButton.layoutIfNeeded()
}
* Обратите внимание: *
когда "buttonType" кнопки _ "UIButtonTypeSystem" , ниже кода недействителен:
[UIView setAnimationsEnabled:NO];
[_button setTitle:@"title" forState:UIControlStateNormal];
[UIView setAnimationsEnabled:YES];
когда "buttonType" of_button "UIButtonTypeCustom" , код выше действителен.
См. ответы Как остановить нежелательную анимацию UIButton при изменении названия?:
[UIView setAnimationsEnabled:NO];
[elapsed setTitle:[NSString stringWithFormat:@"%.2i:%.2i:%.2i:%.2i",days,hours,minutes,seconds] forState:UIControlStateNormal];
[UIView setAnimationsEnabled:YES];
По умолчанию "setTitle" поведение определенно является ненавистным!
Мое решение:
[UIView setAnimationsEnabled:NO];
[_button layoutIfNeeded];
[_button setTitle:[NSString stringWithFormat:@"what" forState:UIControlStateNormal];
[UIView setAnimationsEnabled:YES];
Кроме того, в раскадровке под свойством кнопки снимите флажок:
И проверьте:
Протестировано и работает с iOS 8.
Я предлагаю вам создать свою настраиваемую кнопку и переопределить метод setTitle.
class UnflashingButton: UIButton {
override func setTitle(title: String?, forState state: UIControlState) {
UIView.setAnimationsEnabled(false)
self.layoutIfNeeded()
super.setTitle(title, forState: state)
UIView.setAnimationsEnabled(true)
}
}
Вы можете просто сделать еще одну функцию для UIButton для удобного использования в будущем.
extension UIButton {
func setTitleWithoutAnimation(_ title: String?, for controlState: UIControlState) {
UIView.performWithoutAnimation {
self.setTitle(title, for: controlState)
self.layoutIfNeeded()
}
}
}
Вот и все!
И просто установите заголовок, как раньше, но замените setTitle
на setTitleWithoutAnimation
Попробуйте это, это работает в более новых версиях IOS:
class CustomButtonWithNoEffect : UIButton {
override func setTitle(_ title: String?, for state: UIControlState) {
UIView.performWithoutAnimation {
super.setTitle(title, for: state)
super.layoutIfNeeded()
}
}
}
Я новичок в программировании и Stackoverflow, поэтому у меня недостаточно репутации, чтобы комментировать напрямую, чтобы развернуть https://stackoverflow.com/users/4673064/daniel-tseng отличный ответ. Поэтому я должен написать свой новый ответ, и это так:
extension UIButton {
func setTitleWithoutAnimation(_ title: String?, for controlState: UIControlState) {
UIView.performWithoutAnimation {
self.setTitle(title, for: controlState)
self.layoutIfNeeded()
}
}
}
Прекрасно работает, за исключением:
Если все мои последующие вызовы в коде "setTitleWithoutAnimation" не указывают отправителя, то я получаю эти странные сообщения, связанные с CoreMedia или CoreData, например "Не удалось унаследовать разрешения CoreMedia от 2526: (null)"
Это, вероятно, довольно основа для кодирования и iOS, но для меня, как нового кодера, он на некоторое время отправил меня в путь кролика, как в: Сегодня расширение не удалось унаследовать разрешения CoreMedia, откуда у людей были интересные ответы, но это НЕ достичь корня моей проблемы.
Итак, я наконец-то обнаружил, что мне нужно пройти через все параметры моей функции без параметров, то есть мне нужно было указать отправителя. Этим отправителем может быть UIButton, Any или AnyObject. Все это сработало, но в конечном итоге возникает конфликт между добавлением расширения кнопки с помощью "self" и последующим конкретным выражением о том, что кнопка использует его.
Опять же, возможно, основной, но новый для меня, поэтому я решил, что стоит поделиться.
Еще один трюк
@IBOutlet private weak var button: UIButton! {
didSet {
button.setTitle(title, for: .normal)
}
}
Это работает, только если вы знаете значение заголовка без каких-либо вызовов API. Заголовок кнопки будет установлен перед загрузкой представления, поэтому вы не увидите анимацию