Можно ли программно обновить заголовок / текст UIButton?

96

У меня есть кнопка UIButton, которая при нажатии вызывает новое представление, где пользователь может изменить некоторые настройки. Когда представление закрывается, я хотел бы обновить заголовок / текст, UIButtonчтобы отразить новое состояние. Я звоню:

[myButton setTitle: @"myTitle" forState: UIControlStateNormal];
[myButton setTitle: @"myTitle" forState: UIControlStateApplication];
[myButton setTitle: @"myTitle" forState: UIControlStateHighlighted];
[myButton setTitle: @"myTitle" forState: UIControlStateReserved];
[myButton setTitle: @"myTitle" forState: UIControlStateSelected];
[myButton setTitle: @"myTitle" forState: UIControlStateDisabled];

Но, похоже, он никогда не отличается от исходного текста / заголовка, как указано в IB.

Джордж Армхолд
источник
2
Вы уверены, что опубликованный код вызывается? Вы установили ПЕРЕРЫВ, чтобы доказать это? Можете ли вы поставить подпись вашего делегата?
Пабло Санта Крус,
3
В стороне, я считаю, что вы можете ссылаться на несколько состояний одновременно: [myButton setTitle: @ "myTitle" forState :( UIControlStateNormal | UIControlStateApplication | UIControlStateHighlighted | ...)]; Обратите внимание на использование побитового оператора ИЛИ в отличие от логического оператора ИЛИ (||). В общем, когда вы имеете дело с такими состояниями, вы можете использовать OR вместе с | оператор. Кто-нибудь поправит меня, если я сильно ошибаюсь. :)
CIFilter
Я бы хотел, чтобы у них был такой, как UIControlStateAll: D
taber
2
Побитовые комбинации, похоже, не работают для меня в iOS5.
Echilon
Здесь та же проблема. Побитовые комбинации у меня не работают на iOS5. / CC @LucasTizma
znq

Ответы:

52

У вас есть кнопка, указанная как IBOutlet в вашем классе контроллера представления, и правильно ли она подключена как выход в Interface Builder (перетащите ctrl из нового выхода ссылки к владельцу файла и выберите свой объект UIButton)? Обычно это проблема, которая возникает у меня, когда я вижу эти симптомы.


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

Кен Песписа
источник
4
Бинго, вот и все, спасибо. Я действительно хочу, чтобы Objective-C просто генерировал исключение NullPointerException в таких случаях, вместо того, чтобы молча делать вид, что можно отправлять сообщение объекту nil. Это кусает меня почти ежедневно ... тьфу!
Джордж Армхолд,
20
ObjC не «делать вид» его ОК , чтобы отправить сообщение на ноль, потому что это нормально для отправки сообщений на ноль ...
Jasarien
1
Проблема здесь не в нулевом указателе. Проблема в том, что IB настроил экземпляр UIButton, на который в коде нет ссылок (через IBOutlet), поэтому им нельзя управлять программно.
CIFilter
112

Я решил проблему, просто установив параметр заголовка для UIControlStateNormal, и он автоматически работает с другими состояниями. Проблема, похоже, возникает, когда вы устанавливаете другой UIControlState.

[myButton setTitle: @"myTitle" forState: UIControlStateNormal];
Yotes
источник
15

Начиная с Swift 4:

    button.setTitle("Click", for: .normal)
Влад Спрейс
источник
13

Я обнаружил еще одну проблему. Возможно, это ошибка, появившаяся в iOS 5, но я подумал, что укажу на нее всем, кто с ней столкнется.

Если вы не установите текст по умолчанию для кнопки в XIB, текст никогда не появится, если вы установите его программно. И если вы установите текст в XIB, любой текст, который вы впоследствии назначите кнопке программно, будет усечен до размера текста по умолчанию.

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

Оскар
источник
1
Я заметил все три типа поведения, и это определенно меня раздражает.
Фли
2
У меня была проблема с усечением (программным изменением текста на что-то более длинное), поэтому я поставил дополнительные пробелы в конце текста, чтобы «зарезервировать» это пространство, когда я изменяю текст на более длинное слово. Это сработало для меня.
mattorb
2
Похоже, что исправить это можно с помощью метода [_button setTitle: @ "title" forState: UIControlStateNormal]; вместо прямого доступа к свойству _button.titleLabel.text. Придерживайтесь вызова метода, и вы, вероятно, получите то, что хотите.
Rymnel
12

Несмотря на то, что проблема с Caffeine Coma была решена, я хотел бы предложить еще одну потенциальную причину, по которой название не отображается в UIButton.

Если вы установите изображение для UIButton, используя

- (void)setImage:(UIImage *)image forState:(UIControlState)state

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

Используйте этот метод вместо

- (void)setBackgroundImage:(UIImage *)image forState:(UIControlState)state

для изображения кнопки и заголовка не будут затронуты.

Я тестировал это с программно созданными кнопками и кнопками, созданными в .xib

Джесси Блэк
источник
7

для быстрого:

button.setTitle("Swift", forState: UIControlState.Normal)                   
Дара Титх
источник
4

Оказывается, документы говорят вам ответ! UIButton проигнорирует изменение заголовка, если он уже имеет атрибутную строку для использования (похоже, это значение по умолчанию, которое вы получаете при использовании построителя интерфейса Xcode).

Я использовал следующее:

[self.loginButton 
     setAttributedTitle:[[NSAttributedString alloc] initWithString:@"Error !!!" attributes:nil] 
     forState:UIControlStateDisabled];
[self.loginButton setEnabled:NO];
CPD
источник
3

Еще одна возможная причина:

Если вы попытаетесь установить заголовок кнопки в (id)initWithNibName: ...методе, ваше свойство кнопки все равно будет равно нулю. Он еще не назначен UIButton.

Вы должны быть уверены, что настраиваете свои кнопки таким методом, как (void)viewWillLoadили (void)viewWillAppear, но вы, вероятно, не захотите устанавливать их так поздно (void)viewDidAppear.

Рэмси
источник
2

Иногда это может быть очень сложно. Самый простой способ - « обновить » вид кнопок!

//Do stuff to your button here.  For example:

[mybutton setEnabled:YES];

//Refresh it to new state.

[mybutton setNeedsDisplay];
Майк Рападас
источник
1

У меня продолжали возникать проблемы с этим, единственным решением было добавить изображение и метку в качестве подпредставлений в uibutton. Затем я обнаружил, что основная проблема заключалась в том, что я использовал UIButton с заголовком: Attributed. Когда я изменил его на Plain, достаточно установить titleLabel.text!

отметка
источник
1

@funroll абсолютно прав. Здесь вы можете увидеть, что вам понадобится. Убедитесь, что функция работает только в основном потоке . Если вы не хотите иметь дело с потоками, вы можете сделать это, например: создать NSUserDefaults и в ViewDidLoad условие проверки была нажата кнопка в другом представлении или нет (в другом представлении, установленном в NSUserDefaults, необходимая информация), и в зависимости от условий, установленных для необходимого заголовка для ваш UIButton, поэтому [yourButton setTitle: @ "Title" forState: UIControlStateNormal];

Daleijn
источник
Это было очень полезно для меня ... оказывается, если вы вызываете setTitle и setNeedsDisplay из фонового потока, View будет обновляться намного позже.
user1111828
0

Убедитесь, что вы находитесь в основном потоке.

Если нет, он все равно сохранит текст кнопки. Он будет там, когда вы проверите объект в отладчике. Но на самом деле это не будет обновлять представление.

Funroll
источник