unable to mantain localization on a UIButton after - objective-c

I am using NSLocalizedString function to change the language of a UIButton
reset.titleLabel.text=NSLocalizedString(#"Reset", nil);
I put this line in the viewDiLoad , viewWillAppear , viewDidAppear , viewDidDisappear and viewWillDisappear
when the View load , the localized version of the text appear , when I click on the button the text change back to the original text that is on the button in the Storyboard and then return to the localized language again right before loading the following view (even the the titlelable never changes values all across these stages!)
I saw that one of the solutions is to have a localized version of the Storyboard but I don t want to do that yest since I will have to maintain all localized versions ... any other solution ?

I would suggest using -setTitle:forState: to change the title. By manually changing the titleLabel.text, you should expect the text to be reset occasionally. Most documentation examples just show manipulating the font size, etc. not the contents, and that is because the titleLabel is set to the currentTitle Since there are multiple states for buttons, iOS has a way to set these where they are stored and to make sure that any image caches are appropriately updated.
[reset setTitle: NSLocalizedString( #"Reset", nil) forState: UIControlStateNormal];
As long as none of the other states are explicitly set, this will be used for all of the states. If you want to change the title for different states, use one of the other state contents.

Related

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:
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.

Custom UIButton background image showing in iOS 6 but not iOS 5

I set the button background in the interface builder, but that wasn't showing up so I set it programmatically. All (but one button... why?) shows on the simulator but never show on a device.
I get this output:
Could not load the "gray_button.png" image referenced from a nib in the bundle with identifier "com.example.ios"
This is the code:
- (void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.getMyTripButton setBackgroundImage:[UIImage imageWithContentsOfFile:
[[self getFullPathname] stringByAppendingPathComponent:#"images/gray_button.png"]]
forState:UIControlStateNormal];
[self.popupButton setBackgroundImage:[UIImage imageWithContentsOfFile:
[[self getFullPathname] stringByAppendingPathComponent:#"images/gray_button.png"]]
forState:UIControlStateNormal];
[self.viewOurPackages reloadData];
}
I have also tried replacing imageWithContentsOfFile with imageNamed and both yield the same results.
I have added the images directory in my Project > Targets > Build Phases > Copy Bundle Resources, but I think this is where it all starts to go wrong and I can't figure out why. Possibly because it's a directory?
I would like to point out that I have double and triple checked that it is not a capitalization/case-sensitive issue.
UPDATE: I have solved the one button not showing. It would seem that real issue is that the images show on iOS6 and NOT on iOS5.
What worked for me was one (or a combination) of the following 3 things:
Make sure your image file is formatted correctly. Sometimes png files need a little coercing. (I think this specifically was my problem)
Make sure your button is of type Custom in the Interface Builder or UIButtonTypeCustom.
If you are setting the image in Interface Builder and it's still not showing, set it explicitly in the code using [button setBackgroundImage:image forState:UIControlStateNormal] (or [button setImage:image forState:UIControlStateNormal] depending on which one you need.
If you are adding a folder to the copy bundles, then instead of referencing the file as gray_button.png, you should reference if from code or xib You will have to include the directory in the name too such as directory/gray_button.png
Steph,
If you used #synthesize for the button in the .h file, then getters and setters are automatically created. Thus (this is a longshot and just a thought) having the name getMyTripButton could be confusing Xcode somehow. Try renaming the variable?
As far as the image not loading... for one of the buttons and not the other... da faq? Is this the only places that gray_button.png is getting called? (for example, you aren't modifying that button somewhere else that may tell it to use that image again). Have you tried putting it in the same directory as the nib that is using it? are you sure getMyTripButton is properly tied from the nib to the code?
Last thing I can think of for now:
you said
I set the button background in the interface builder, but that wasn't
showing up so I set it programmatically. All (but one button... why?)
shows on the simulator but never show on a device
do you have popupButton's background image also set in the nib/interface builder? if you already have it set there and are setting it again here, it may be that it isn't really getting set in the code at all and is just using what is in interface builder which could explain why getMyTripButton may not be showing up/showing the background image.
If I think of anything else that could be causing the issue i'll edit this post. Good luck, and hang in there.

Embedding a field editor in a NSScrollView

Has anyone ever had experience embedding a field editor (for a NSTextField) inside a scroll view? I'm trying to make the NSTextField scrollable while editing.
Things I've tried:
Dynamically embed it when the custom field editor's -becomeFirstResponder gets called. This semi works; the problem is that when the NSTextField gets resized during editing the custom field editor no longer gets resized with it (and I need this - making an accordion
style application)
Create a "masquerading" field editor out of a NSScrollView, and using NSInvocation forward the methods to the actual surrogate field editor. This is the method I really hope would work; I've implemented all the methods as listed here; but I get an EXC_BAD_ACCESS whenever the field editor is actually loaded (e.g. when I call [customTextField selectText:nil]). I can't seem to pry any information out of the debugger even with Zombies enabled, and looking at the logs of NSObjCMessageLoggingEnabled yields nothing either. It seems like these guys got it working but that was seven years ago.
The last resort would be to drop NSTextFields completely and use NSTextViews (or instead of relying on the field editor mechanism, write one myself), but since I have many rows of data of which only one will be edited at a time, I don't want to instantiate a NSTextView for every single one of them... but then, perhaps it won't be so bad.
I ended up using option 1, and getting it to work without much difficulty. Option 2 was a complete dead end because EXC_BAD_ACCESS popped up everywhere I went.
My custom field editor now keeps a reference to a (custom) scroll view to embed itself in (vvScrollView), and inserts it into the view hierarchy. My code inside my custom field editor (NSTextView) for embedding it inside a scroll view, which is called as soon as the field editor becomes first responder and is automatically inserted into the view hierarchy:
- (void)embedSelfInScrollView {
NSView *realSuperview = [[self superview] superview];
// [self superview] is some kind of private NSClipView class
if ([realSuperview isKindOfClass:[NSTextField class]]) { // the expected behavior: this may change? TODO make less prone to chance
[realSuperview addSubview:[self vvScrollView]]; // insert into view
[[self vvScrollView] setFrameSize:[realSuperview frame].size]; // se the initial size equivalent to control size so it can autoresize the same way
// add the scrollview into the view hierarchy
[[self vvScrollView] setDocumentView:self]; // removes self from previous superview
}
}
The initial problem I had was that I was trying to insert the scrollview into the superview immediately above the field editor's (the private class of NSClipView) which broke almost every automatic sizing option (because I want to be able to resize the NSTextField while editing). Going a step further and bypassing the private class seems to work, but almost seems arbitrary.

How can I programmatically add a text field with a decimal pad keyboard in Xcode 4?

I needed to add a UIKeyboardTypeDecimalPad keyboard to a decimal field, which can only be done programatically. I need the full code (I'm pretty new to Objective-C) to make a UIKeyboardTypeDecimalPad pop up when someone touches inside the text box. I'd also like to add the text field programmatically.
Basically, I need to add a text field with a UIKeyboardTypeDecimalPad keypad. Or, if possible, just the keypad to a text field made in Interface Builder.
Does anyone know a good tutorial for this or can anyone give me the full code themselves, and tell me where I need to put it (the .m or .h or what?)?
Thanks!
Update: As mentioned in the comment below, could I see example code for an app that does this?
To set the keyboard type to UIKeyboardTypeDecimalPad, just assign that value to the text field's keyboardType property.
textField.keyboardType = UIKeyboardTypeDecimalPad;
Adding a text field programmatically is only slightly more work: UITextField *textField = [[[UITextField alloc] initWithFrame:frame] autorelease]; to create it, then set any properties you need to set, and add it to the appropriate view with addSubview:.
In your view controller's viewDidLoad method is a good place for this sort of thing. Or if you're loading a view without a controller from the nib, use the view's awakeFromNib method.

What is the proper way to align UITableViewCells when only some have an imageView?

I am new to iPhone programming and working on my first real application (i.e. one not written in a book or online) and I've run into a small problem which I could solve a multitude of ways, but feel like there should be a good solution that perhaps I am just missing.
Here is the scenario: I have a UITableView with a bunch of standard UITableViewCells in it. What I want to do is toggle a green check mark when the cell is selected and I have that part working (note: I'm already using the accessoryType for something else, so I can't use it for the checkmark...besides, it's not as pretty). Unfortunately, when I toggle the checkmark like so:
if (...) {
cell.imageView.image = [UIImage imageNamed:#"checkmark.png"];
} else {
cell.imageView.image = nil;
}
It makes the cell's label bounce back and forth depending on whether it is checked or not. What is the proper way to align the cell's text (set via cell.textLabel.text) regardless of whether or not it has an image set? The solutions I have come up with are:
Create a blank 40x40 png image in Photoshop and set the unchecked to that
Create a blank 40x40 image solely in code
Set some setting that I don't know about that will align it for me
Create a subclass of UITableCellView that does what I need (which would be stupid, I'd just go with option 1...)
Suggestions? Thoughts? Comments? Thank you very much :-)
P.S. I'd like the solution to work with OS 3.0 and 4.0 if that makes any sort of difference.
Option 1 is the way to go for a standard cell.
Strictly speaking, you do not have to subclass UITableViewCell to customize the layout. You can add any views you wish to the contentView. So you can add a UILabel and UIImageView to the contentView instead of using the imageView and textLabel properties.