Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting the text on UIButtonLabel on a PLUICameraViewController

I'm trying to set the text of the "Retake" and "Use" buttons on the PLUICameraViewController. I've programmatically navigated through the view hierarchy and found a few UIButtonLabel objects. Logging the text of these shows what I expect: "Retake", "Cancel" etc. However setting the text doesn't work. The buttons just keep their original text. Here's what I've tried:

if (q is a subclass of UIButtonLabel)
    if ([q respondsToSelector:@selector(setText:)])
        [q performSelector:@selector(setText:) withObject:@"zzz"];

The code runs w/o crashing. Also respondsToSelector is returning YES. How can I make the text on the buttons update?

By the way I'm aware of other approaches involving custom buttons, my own views etc. I'm really curious from an Objective-C/runtime/iOS perspective why the above code doesn't work.

Also note I'm doing this in

 navigationController:willShowViewController:viewController:animated:
like image 938
MrDatabase Avatar asked Jan 25 '26 08:01

MrDatabase


1 Answers

In this case, I don't think it's an issue of Private APIs, per se. This is just the way UIButton works.

Yes, the title of the button is a UILabel, and in practice, it is probably/currently an instance of the private class UIButtonLabel. But, the way Apple intends for you to change the title text is to use the methods in UIButton itself:

[self.button setTitle: @"newTitle" forState: UIControlStateNormal];
[self.button setTitle: @"newTitle" forState: UIControlStateSelected];

instead of trying to drill down into the button's subview heirarchy, find a button label, and call setText:.

Here's the relevant API documentation

As to why it doesn't work, I suppose that's because Apple wants it that way.

For one, changing a button's title is expected to be a normal use case. So, for convenience, they probably wanted to give you an easy method to call, directly in the UIButton interface. If they forced you do drill down into the view hierarchy, not only would you have to write more code, but it makes it a little harder for Apple to change the underlying implementation of a button. They may want to preserve the ability to change it later, and for that, it's better for them to keep some sort of wrapper APIs at the UIButton level.

Also, if you directly change the text on the button label, you are circumventing their design, where the label text depends on the button state (e.g. normal, highlighted, selected, etc.) Even though most people probably use the same button text for all states, the design allows for state-dependent text, and therefore, hiding the underlying UIButtonLabel helps enforce this design.

That's my guess as to their motivation.

So, to enforce this, it's entirely possible that in their implementation of UIButtonLabel setText:, they decline to update the text after the button has been initialized. After that, you have to use the setTitle:forState: method.

like image 57
Nate Avatar answered Jan 27 '26 22:01

Nate



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!