czy można programowo aktualizować tytuł / tekst UIButton?

96

Mam UIButton, które po naciśnięciu powoduje wyświetlenie nowego widoku, w którym użytkownik może zmienić niektóre ustawienia. Po odrzuceniu widoku chciałbym zaktualizować tytuł / tekst, UIButtonaby odzwierciedlić nowy stan. Dzwonię:

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

Ale wydaje się, że nigdy nie zmienia się w stosunku do oryginalnego tekstu / tytułu określonego w IB.

George Armhold
źródło
2
Czy na pewno wywoływany jest wysłany kod? Czy umieściłeś BREAKPOINT, aby to udowodnić? Czy możesz wysłać podpis swojego pełnomocnika?
Pablo Santa Cruz
3
Na marginesie, uważam, że można jednocześnie odwoływać się do wielu stanów kontrolnych: [myButton setTitle: @ "myTitle" forState :( UIControlStateNormal | UIControlStateApplication | UIControlStateHighlighted | ...)]; Zwróć uwagę na użycie bitowego operatora OR w przeciwieństwie do logicznego operatora OR (||). Ogólnie rzecz biorąc, kiedy masz do czynienia z takimi stanami, możesz je LUB razem z | operator. Niech ktoś mnie poprawi, jeśli się mylę. :)
CIFilter
Żałuję, że nie mają takiego jak UIControlStateAll: D
taber
2
Wydaje się, że kombinacje bitowe nie działają dla mnie w iOS5.
Echilon,
Ten sam problem tutaj. Kombinacje bitowe nie działają dla mnie na iOS5. / CC @LucasTizma
znq

Odpowiedzi:

52

Czy masz przycisk określony jako IBOutlet w swojej klasie kontrolera widoku i czy jest on prawidłowo podłączony jako gniazdo w programie Interface Builder (przeciągnij klawiszem Ctrl z nowego gniazdka referencyjnego do właściciela pliku i wybierz obiekt UIButton)? To zwykle problem, który mam, gdy widzę te objawy.


Edycja: Chociaż tak nie jest w tym przypadku, coś takiego może się również zdarzyć, jeśli ustawisz przypisany tytuł do przycisku, a następnie spróbujesz zmienić tytuł, a nie przypisany tytuł.

Ken Pespisa
źródło
4
Bingo, to było to, dzięki. Naprawdę chciałbym, żeby Objective-C po prostu rzucił wyjątek NullPointerException w takich przypadkach, zamiast po cichu udawać, że można wysłać wiadomość do obiektu zerowego. To gryzie mnie prawie codziennie ... ugh!
George Armhold
20
ObjC nie „udaje”, że wysyłanie wiadomości do zera jest w porządku , ponieważ wysyłanie wiadomości do zera jest w porządku ...
Jasarien
1
Problem tutaj nie jest wskaźnikiem zerowym. Problem polega na tym, że IB skonfigurował instancję UIButton, do której nie odwołuje się poprawnie w kodzie (przez IBOutlet), więc nigdy nie można nią manipulować programowo.
CIFilter
112

Rozwiązałem problem po prostu ustawiając parametr tytułu dla UIControlStateNormal i automatycznie działa on na innych stanach. Wydaje się, że problem występuje, gdy ustawisz inny stan UIControl.

[myButton setTitle: @"myTitle" forState: UIControlStateNormal];
Yotes
źródło
15

Od wersji Swift 4:

    button.setTitle("Click", for: .normal)
Vlad Spreys
źródło
13

Odkryłem inny problem. Może to być błąd wprowadzony w iOS 5, ale pomyślałem, że wskazałbym go każdemu, kto go spotka.

Jeśli nie ustawisz żadnego domyślnego tekstu dla przycisku w XIB, żaden tekst nie pojawi się, jeśli ustawisz go programowo. A jeśli ustawisz tekst w XIB, każdy tekst, który później przypiszesz do przycisku, zostanie programowo obcięty do rozmiaru tekstu domyślnego.

Na koniec, jeśli wyświetlasz widok za pomocą przycisku, a następnie wywołujesz inny widok (taki jak arkusz akcji), a następnie go odrzucasz, tekst przypisany do przycisku programowo zostanie usunięty, a podpis przycisku powróci do tego, co ustawisz w XIB.

Oscar
źródło
1
Zauważyłem wszystkie te trzy zachowania i jest to z pewnością irytujące.
Pchła
2
Miałem problem z obcinaniem (programistyczna zmiana tekstu na dłuższy), więc wstawiłem dodatkowe spacje na końcu tekstu, aby „zarezerwować” to miejsce, gdy zmieniam tekst na dłuższe słowo. To zadziałało dla mnie.
mattorb
2
Wygląda na to, że rozwiązaniem tego problemu jest użycie metody [_button setTitle: @ "title" forState: UIControlStateNormal]; zamiast bezpośredniego dostępu do właściwości _button.titleLabel.text. Trzymaj się wywołania metody, a prawdopodobnie otrzymasz to, czego chcesz.
Rymnel,
12

Mimo że problem Caffeine Coma został rozwiązany, chciałbym przedstawić inną potencjalną przyczynę, dla której tytuł nie pojawia się na UIButtonie.

Jeśli ustawisz obraz dla UIButton za pomocą

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

Może obejmować tytuł. Przekonałem się o tym na własnej skórze i wyobrażam sobie, że niektórzy z was czytają tę stronę z tego samego powodu.

Zamiast tego użyj tej metody

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

obrazu przycisku i tytuł pozostanie bez zmian.

Przetestowałem to z programowo utworzonymi przyciskami i przyciskami utworzonymi w formacie .xib

Jesse Black
źródło
7

na szybko:

button.setTitle("Swift", forState: UIControlState.Normal)                   
Dara Tith
źródło
4

Okazuje się, że doktorzy mówią ci odpowiedź! UIButton zignoruje zmianę tytułu, jeśli ma już przypisany ciąg znaków do użycia (z wydaje się być domyślnym, jaki otrzymujesz podczas korzystania z konstruktora interfejsu Xcode).

Użyłem następujących:

[self.loginButton 
     setAttributedTitle:[[NSAttributedString alloc] initWithString:@"Error !!!" attributes:nil] 
     forState:UIControlStateDisabled];
[self.loginButton setEnabled:NO];
CPD
źródło
3

Jest to jeszcze jedna możliwa przyczyna:

Jeśli spróbujesz ustawić tytuł przycisku w (id)initWithNibName: ...metodzie, twoja właściwość przycisku nadal będzie wynosić zero. Nie został jeszcze przypisany do UIButton.

Musisz mieć pewność, że ustawiasz przyciski metodą (void)viewWillLoadlub (void)viewWillAppear, ale prawdopodobnie nie chcesz ustawiać ich tak późno, jak (void)viewDidAppear.

Ramsey
źródło
2

Czasami może się to naprawdę skomplikować. Prostym sposobem jest „ odświeżenie ” widoku przycisków!

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

[mybutton setEnabled:YES];

//Refresh it to new state.

[mybutton setNeedsDisplay];
Mike Rapadas
źródło
1

Ciągle miałem z tym problemy, jedynym rozwiązaniem było dodanie obrazu i etykiety jako podglądów podrzędnych do uibutton. Potem odkryłem, że głównym problemem było to, że używałem przycisku UIButton o tytule: Attributed. Kiedy zmieniłem go na Zwykły, samo ustawienie titleLabel.text załatwiło sprawę!

znak
źródło
1

@funroll ma całkowitą rację. Tutaj możesz zobaczyć, czego będziesz potrzebować. Upewnij się, że funkcja działa tylko w głównym wątku . Jeśli nie chcesz zajmować się wątkami, możesz zrobić tak na przykład: utwórz NSUserDefaults iw ViewDidLoad warunek sprawdzania został naciśnięty przycisk w innym widoku lub nie (w innym widoku ustawionym w NSUserDefaults potrzebne informacje) iw zależności od warunków ustaw potrzebny tytuł dla Twój UIButton, więc [yourButton setTitle: @ "Title" forState: UIControlStateNormal];

daleijn
źródło
To było dla mnie bardzo przydatne. Okazuje się, że jeśli wywołasz setTitle i setNeedsDisplay z wątku w tle, widok zostanie zaktualizowany znacznie później.
user1111828
0

Upewnij się, że jesteś w głównym wątku.

Jeśli nie, nadal zapisze tekst przycisku. Będzie tam, gdy sprawdzisz obiekt w debugerze. Ale tak naprawdę nie zaktualizuje widoku.

funroll
źródło