how to switch language at runtime inside the app? - iphone

I have a requirement to switch UI language at run-time by opening and selecting a popup menu. I did some reading on cocoa's internationalization but found it not suitable for my project since it requires user to make changes in the system setting.
Post like "http://stackoverflow.com/questions/1669645/how-to-force-nslocalizedstring-to-use-a-specific-language" suggests setting the AppleLanguages would also require an app-restart.
I wonder if I can (a) create multiple NIBs and call initWithNib according to the current language or (b) use one NIB but create a plist of strings and make a function to set title string for all the texts in all my viewWillAppear. Which solution sounds better or please let me if there is a third way.
Thanks
Leo

The simplest way I can think of is reloading all your views, and updating the text property of all text components (such as UILabel, UITextField, etc.). The language specific text to be set can be returned by a method of yours, something like-
-(NSString*) localizedStringForKey: (NSString*)key andLanguage: (NSString*)lang
{
if([lang isEqualToString:#"en"])
{
if(key == #"hello")
return #"Hello";
//and so on...
}
else if([lang isEqualToString:#"fr"])
{
if(key == #"hello")
return #"Bonjour";
//and so on...
}
}
P.S: Here I am returning hard-coded values, but you can read them from language-specific plists of yours.

Related

How to grab a path for app.navigationBars

I faced an issue that is combined with UI testing of the view.
I have an issue with an incorrect path to the element that is the text field, which is Search. I would like to achieve the state when the code for app.navigationBars will be resistant for different languages. That's why right now it looks the following way:
var airportsSearchTextField: XCUIElement { app.navigationBars["Airports"].searchFields["Search"] }
This won't work properly for another language like English. I know that it could be possible to add accessibilityIdentifier, but I'm not sure where and maybe for navigationBar is there any other way to implement a better solution to grab this element within UI tests?
func selectFlight() { airportsSearchTextField.tap() }

Updating an NSTextField while controlling an NSTableView [duplicate]

What's the easiest way to have an NSTextField with a "recommendation list" dynamically shown below it as the user types? Just like Safari's address bar that has a menu of some sorts (I'm pretty confident Safari's address bar suggestions is menu since it has rounded corners, blue gradient selection, and background blurring).
I've tried using NSTextView's autocompletion facility but found it was inadequate:
It tries to complete words instead of the whole text fields – in other words, selecting an autocomplete suggestion will only replace the current word.
It nudges the autocompletion list forward and align it with the insertion point instead of keeping it align with the text field.
In the sample screenshot above whenever I selected the autocomplete suggestion the text field only replaces K with the suggested item in the list, which results in Abadi Abadi Kurniawan.
These are what I'd like to achieve:
Whenever a suggestion is selected, the entire text field is replaced with the suggestion.
Keep the suggestion list aligned with the text field's left side.
Note: This is not a question about adding progress indicator behind a text field.
The Safari address bar uses a separate window. Apple has example project CustomMenus and it only takes an hour or two to customize it.
Developer session explaining what has to be done Key Event Handling in Cocoa Applications
If you want to be able to select multiple words you need to provide own FieldEditor (credits should go for someone else)
- (id)windowWillReturnFieldEditor:(NSWindow *)sender toObject:(nullable id)client;
{
if ([client isKindOfClass:[NSSearchField class]])
{
if (!_mlFieldEditor)
{
_mlFieldEditor = [[MLFieldEditor alloc] init];
[_mlFieldEditor setFieldEditor:YES];
}
return _mlFieldEditor;
}
return nil;
}
- (void)insertCompletion:(NSString *)word forPartialWordRange:(NSRange)charRange movement:(NSInteger)movement isFinal:(BOOL)flag
{
// suppress completion if user types a space
if (movement == NSRightTextMovement) return;
// show full replacements
if (charRange.location != 0) {
charRange.length += charRange.location;
charRange.location = 0;
}
[super insertCompletion:word forPartialWordRange:charRange movement:movement isFinal:flag];
if (movement == NSReturnTextMovement)
{
[[NSNotificationCenter defaultCenter] postNotificationName:#"MLSearchFieldAutocompleted" object:self userInfo:nil];
}
}
This only addresses half of your answer, but I believe you need to subclass NSTextView and implement the - (NSRange)rangeForUserCompletion method, returning the range of the entire string in the text field. This should make sure that it doesn't just autocomplete the most recently entered word.
If you want a custom menu, you're going to have to do that yourself, probably by implementing the -controlTextDidChange: method and displaying a custom view with a table when appropriate.

iPhone: UITextfield validation

I checked the existing examples here in S.O, for my case which one do you think is better,
There are many textfields in one view and I want to validate them just when the user is editing that particular textfield, cause otherwise I have to validate them together when user press next on the screen than I have show all validation messages which I dont want to bother with. I want to validate the textfield in 2 different ways, if its a number input I want to validate it in a defined range e.g if number between between 5 and 1000 or if its a text then if the lenght of the text is in a defined range e.g between 2 and 10 characters. And the user must be able to enter any input out of range.
Which is better;
Using textField:shouldChangeCharactersInRange
or something like this:
[textField addTarget:self action:#selector(validateField:) forControlEvents:UIControlEventEditingChanged];
And either the case how can I check on runtime that the number entered is in range and dont allow user to enter bigger or smaller numbers
Good one.
The answer for your question is
1) Set the tag values to all the textfields.
2) Use UIControlEventEditingDidBegin and trigger a method to validate the textfield before the currentone.
[textfield1 setTag:1];
[textfield2 setTag:2];// make sure to set tag values incrementally
[textfield2 addTarget:self #selector(validate:) forControlEvents:UIControlEventEditingDidBegin];
-(void) validate:(id) sender
{
// 10 is the number of textfields, change it accordingly.
if(sender.tag!=1 && sender.tag!=10)
{
//validate textfield with tag sender.tag-1
}
else
{
//handle first and last textfield here
}
}
Try this, probably this will solve your problem.
Actually, both of your approaches will be just fine! Using the delegate of the UITextField to call textField:shouldChangeCharactersInRange and perform the validation there is an equally good approach as using Target & Action. In both situations, you define a handler that receives the calling UITextField as an argument (one implementation of this is what #Anil Kumar suggested in his answer to tag the text fields. but this is actually not even required, you can just call isEqual: on the text fields directly to check for equality).
Personally, I tend to use delegation for these kinds of tasks though.
Update: If you want to go really fancy on this problem, you'll use Reactive Cocoa. The April Tech Talk of the Ray Wenderlich Gang had a great session on it and also discusses the issue of from validation, so it'll just match your case! :)
Take a look at TextFieldValidator developed in swift

Change color of text in UITableViewCell based on the text

I'm trying to change the text of a custom UITableViewCell based on whether the text says Closed or not. However, when the text is Closed, the color will not change. Here is a code snippet. http://pastie.org/1078690
Thanks.
Simple equality does not work for NSString objects. Instead of
if ([dict objectForKey:#"status"] == #"Closed") {
do
if ([[dict objectForKey:#"status"] isEqualToString:#"Closed"]) {
That will work - but I bet you could find a more efficient way of conditionally changing color than checking a string inside cellForRowAtIndexPath. Trouble is this method will be called often. You are reusing cells, which is an efficiency measure, that's good. But then you do something relatively expensive like a string comparison - how about adding a BOOL that could be checked instead, and setting it when you decide on the cell's text?

Display blanks instead of 0 or 0.0 in a BIRT report

When using an aggregate control in some reports you would prefer to see a blank field instead of 0. There does not appear to be a way to do this automatically. Does anyone have a way that this can be done. Note, you want to maintain the '0' value for the field in cases when you export, but you want to show a blank when rendering to PDF or HTML.
There are a number of ways to solve this. The two primary are to use either visibility rules or highlights to create conditional formatting. The visibility is particularly attractive since it is easy to only apply the format rules to particular types of output (e.g. HTML).
For this particular case, there are two problems with these approaches. First, I want a general solutions where I don't have to specify the text color. In other words, when the condition is true (value of 0) then I want my text color to match the background color. In that way if someone changes the backgroundColor for the control, the code still works.
The other issue is that in this case I am using dynamic column binding which does not support value lookup.
The solution that I created was to add a JavaScript function called hideMe as shown below.
function hideText (dataControl){
if (dataControl.getValue() == 0) {
var color = dataControl.getStyle().getBackgroundColor();
var parentItem = dataControl.getParent();
do {
if (color == null && parentItem != null) {
color = parentItem.getStyle().getBackgroundColor();
parentItem = parentItem.getParent();
} else {
break;
}
} while (color == null);
dataControl.getStyle().color = color;
}
}
Once this function has been added to the report (in my case an included javascript file) I just call it from the OnCreate method of the control.
hideText(this);
This can also be done using Java Event Handlers but this method seems to be easier.
Just an FYI, after working with this for a while longer, I have found that it is just easier to use Visibility rules. The one big advantage is that you can easily configure different visibility for different output formats. So for PDF it may be best to use blanks, but for Excel you may want the 0 values.