é possível atualizar o título / texto UIButton programaticamente?

96

Eu tenho um UIButton, que quando pressionado, abre uma nova visualização onde o usuário pode alterar algumas configurações. Quando a exibição for descartada, gostaria de atualizar o título / texto do UIButtonpara refletir o novo estado. Estou ligando:

[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];

Mas nunca parece mudar do texto / título original conforme especificado no IB.

George Armhold
fonte
2
Tem certeza de que o código postado está sendo chamado? Você colocou um BREAKPOINT para provar isso? Você pode postar a assinatura do seu delegado?
Pablo Santa Cruz
3
À parte, acredito que você pode fazer referência a vários estados de controle de uma vez: [myButton setTitle: @ "myTitle" forState :( UIControlStateNormal | UIControlStateApplication | UIControlStateHighlighted | ...)]; Observe o uso do operador OR bit a bit em oposição ao operador OR lógico (||). Em geral, quando você está lidando com estados como este, você pode fazer OR junto com o | operador. Alguém me corrija se eu estiver totalmente enganado. :)
CIFilter
Eu gostaria que eles tivessem um como UIControlStateAll: D
taber
2
As combinações bit a bit não parecem funcionar para mim no iOS5.
Echilon de
Mesmo problema aqui. Combinações bit a bit não funcionam para mim no iOS5. / CC @LucasTizma
znq

Respostas:

52

Você tem o botão especificado como um IBOutlet em sua classe de controlador de visualização e ele está conectado corretamente como um outlet no Interface Builder (ctrl arraste do novo outlet de referência para o proprietário do arquivo e selecione seu objeto UIButton)? Geralmente é esse o problema que tenho quando vejo esses sintomas.


Editar: Embora não seja o caso aqui, algo como isso também pode acontecer se você definir um título atribuído ao botão e, em seguida, tentar alterar o título e não o título atribuído.

Ken Pespisa
fonte
4
Bingo, era isso, obrigado. Eu realmente gostaria que Objective-C apenas jogasse um NullPointerException em casos como esse, em vez de fingir silenciosamente que está tudo bem enviar uma mensagem para um objeto nulo. Isso me morde quase diariamente ... ugh!
George Armhold
20
ObjC não 'finge' que está OK enviar uma mensagem para nulo, porque está OK enviar mensagens para nulo ...
Jasarien
1
O problema aqui não é um ponteiro nulo. O problema é que o IB configurou uma instância de UIButton que não está sendo referenciada corretamente no código (via IBOutlet), portanto, nunca pode ser manipulada programaticamente.
CIFilter
112

Resolvi o problema apenas definindo o parâmetro title para UIControlStateNormal, e ele funciona automaticamente nos outros estados. O problema parece ser quando você define outro UIControlState.

[myButton setTitle: @"myTitle" forState: UIControlStateNormal];
Yotes
fonte
15

A partir do Swift 4:

    button.setTitle("Click", for: .normal)
Vlad Spreys
fonte
13

Eu descobri outro problema. Pode ser um bug introduzido no iOS 5, mas pensei em apontá-lo para qualquer pessoa que o encontrasse.

Se você não definir nenhum texto padrão para o botão no XIB, nenhum texto aparecerá se você defini-lo programaticamente. E se você definir o texto no XIB, qualquer texto que você atribuir posteriormente ao botão programaticamente será truncado para o tamanho do texto padrão.

E, finalmente, se você estiver mostrando a visualização com seu botão e, em seguida, invocar outra visualização (como uma ActionSheet) e dispensá-la, o texto que você atribuiu ao botão programaticamente será apagado e a legenda do botão retornará ao que você definiu no XIB.

Oscar
fonte
1
Eu percebi todos esses três comportamentos e isso é certamente irritante.
Flea de
2
Eu tive o problema de truncamento (alterar o texto para algo mais longo programaticamente), então coloquei espaços extras no final do texto para 'reservar' esse espaço para quando eu alterar o texto para uma palavra mais longa. Isso funcionou para mim.
Mattorb
2
Parece que a correção para isso é usar o método [_button setTitle: @ "title" forState: UIControlStateNormal]; em vez de acessar a propriedade _button.titleLabel.text diretamente. Fique com a chamada de método e provavelmente você obterá o que deseja.
Rymnel de
12

Mesmo que o problema do Caffeine Coma tenha sido resolvido, eu gostaria de oferecer outra causa potencial para o título não aparecer em um UIButton.

Se você definir uma imagem para o UIButton usando

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

Pode cobrir o título. Descobri isso da maneira mais difícil e imagino que alguns de vocês acabem lendo esta página pelo mesmo motivo.

Use este método

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

para a imagem do botão e o título não serão afetados.

Eu testei isso com botões criados programaticamente e botões criados em um .xib

Jesse Black
fonte
7

para rápido:

button.setTitle("Swift", forState: UIControlState.Normal)                   
Dara Tith
fonte
4

Acontece que os documentos lhe dizem a resposta! O UIButton irá ignorar a mudança do título se já tiver uma String de Atributo para usar (parece ser o padrão que você obtém ao usar o construtor de interface Xcode).

Usei o seguinte:

[self.loginButton 
     setAttributedTitle:[[NSAttributedString alloc] initWithString:@"Error !!!" attributes:nil] 
     forState:UIControlStateDisabled];
[self.loginButton setEnabled:NO];
CPD
fonte
3

Mais uma causa possível é esta:

Se você tentar definir o título do botão no (id)initWithNibName: ...método, então você é propriedade de botão ainda será nulo. Ainda não foi atribuído ao UIButton.

Você deve ter certeza de que está configurando seus botões em um método como (void)viewWillLoadou (void)viewWillAppear, mas provavelmente não deseja configurá-los tão tarde quanto (void)viewDidAppear.

Ramsey
fonte
2

Às vezes, pode ficar muito complicado. A maneira mais fácil é " atualizar " a visualização do botão!

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

[mybutton setEnabled:YES];

//Refresh it to new state.

[mybutton setNeedsDisplay];
Mike Rapadas
fonte
1

Continuei tendo problemas com isso, a única solução era adicionar uma imagem e rotular como subvisualizações ao uibutton. Então descobri que o principal problema era que estava usando um UIButton com o título: Atribuído. Quando eu mudei para Plain, apenas definir o titleLabel.text fez o truque!

Marca
fonte
1

@funroll está absolutamente certo. Aqui você pode ver o que você precisa. Certifique-se de que a função seja executada apenas no thread principal . Se você não quiser lidar com tópicos, pode fazer assim, por exemplo: criar NSUserDefaults e em ViewDidLoad a condição de verificação foi pressionada em outra View ou não (em outra View definida em NSUserDefaults informações necessárias) e dependendo das condições definidas título necessário para seu UIButton, então [yourButton setTitle: @ "Title" forState: UIControlStateNormal];

daleijn
fonte
Isso foi muito útil para mim .. acontece que se você chamar setTitle e setNeedsDisplay de um thread de segundo plano, a visualização será atualizada muito mais tarde.
user1111828
0

Certifique-se de que você está no tópico principal.

Caso contrário, ele ainda salvará o texto do botão. Ele estará lá quando você inspecionar o objeto no depurador. Mas isso não atualizará a visualização.

funroll
fonte