Can't query iOS for current user language - ios

I'm trying to determine the user language in iOS. StackOverflow has several answers on this topic which has greatly helped me out, such as this one: Getting current device language in iOS?
I can successfully retrieve the value I'm looking for in NSLog (i.e. "en" or "de") but every time I question this with an if/then statement it doesn't appear to work. I have this in my viewDidLoad for testing:
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *myLanguage = [[NSLocale preferredLanguages] objectAtIndex:0];
NSLog(#"The current languague is %#.", myLanguage);
if (myLanguage == #"de") {
self.myLabel.text = #"German";
} else if (myLanguage == #"en") {
self.myLabel.text = #"English";
} else {
self.myLabel.text = #"didn't work";
}
}
No matter if the device is set to English or German only the last else statement is displayed. NSLog however correctly displays either en or de.
What am I doing wrong?

NSString comparison is done with isEqualToString: method. In your code you are comparing two different NSString objects, while instead you have to compare the contents of each one of them.
If you have two objects of any kind, they are always different, even if all their members have the same values. That's why methods like this exist, to compare objects based on their members.
Replace:
if (myLanguage == #"de")
with
if ([myLanguage isEqualToString:#"de"])
and the same for the else ifs in your code.

Related

App Not Sending PNGs

Trying to learn by digging through some code.
Have an accessory button, when its pressed it loads up a menu so the user can pick either a picture from photo library or video (works perfect) have also a sticker menu that pops up similarly to the photo library. The sticker pops up accordingly, only have one if that matters. However when I select it nothing happens. The view is dismissed and it should be sent however it is not.v THE NSLog prints my check statement, I have even added the JSQ sound to play and it does it as well. Working with Firebase/Parse.
It seems to call everything just doesn't attach the PNG from the grid view to the message.
StickerView.m
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
[collectionView deselectItemAtIndexPath:indexPath animated:YES];
NSString *file = stickers2[indexPath.item];
NSString *sticker = [file stringByReplacingOccurrencesOfString:#"#2x.png" withString:#""];
if (delegate != nil) [delegate didSelectSticker:sticker];
NSLog(#"Sticker Sent");
[self dismissViewControllerAnimated:YES completion:nil];
}
Chat.m
- (void)didSelectSticker:(NSString *)sticker
{
[self messageSend:sticker Video:nil Picture:nil Audio:nil];
}
messageSend
- (void)messageSend:(NSString *)text Video:(NSURL *)video Picture:(UIImage *)picture Audio:(NSString *)audio
{
Outgoing *outgoing = [[Outgoing alloc] initWith:groupId View:self.navigationController.view];
[outgoing send:text Video:video Picture:picture Audio:audio Sticker:sticker];
[JSQSystemSoundPlayer jsq_playMessageSentSound];
[self finishSendingMessage];
}
LOG
NSString *file = stickers2[indexPath.item];
NSLog (#"%d",indexPath.item);
NSLog (#"%#",file);
NSString *sticker = [file stringByReplacingOccurrencesOfString:#"#2x.png" withString:#"#2x.png"];
NSLog (#"%#",sticker);
if (delegate != nil) [delegate didSelectSticker:sticker];
NSLog(#"Sticker Sent");
[self dismissViewControllerAnimated:YES completion:nil];
indexPath returns a numerical value based on which sticker is selected. These are loaded into the mutableArray based on file name. If the file name contains a string of #"foo" it is loaded into the array. it could be one or one million value based on how many are loaded in. However it does correspond correctly to the selections. One is properly returned when object one is selected and 2 is properly selected and so on.
File name is returned as the correct file name.
Sticker was returned incorrectly based on your suspicious line of code, I have replaced it to not removed the extensions but did not delete it as of yet. Now returning the same value as File.
Outgoing
- (void)send:(NSString *)text Video:(NSURL *)video Picture:(UIImage *)picture Audio:(NSString *)audio Sticker:(NSString *)sticker
{
NSMutableDictionary *item = [[NSMutableDictionary alloc] init];
item[#"userId"] = [PFUser currentId];
item[#"name"] = [PFUser currentName];
item[#"date"] = Date2String([NSDate date]);
item[#"status"] = TEXT_DELIVERED;
item[#"video"] = item[#"thumbnail"] = item[#"picture"] = item[#"audio"] = item[#"latitude"] = item[#"longitude"] = #"";
item[#"video_duration"] = item[#"audio_duration"] = #0;
item[#"picture_width"] = item[#"picture_height"] = #0;
if (text != nil) [self sendTextMessage:item Text:text];
else if (video != nil) [self sendVideoMessage:item Video:video];
else if (picture != nil) [self sendPictureMessage:item Picture:picture];
else if (audio != nil) [self sendAudioMessage:item Audio:audio];
else if (sticker !=nil) [self sendSticker:item Sticker:sticker];
else [self sendLoactionMessage:item];
}
sendSticker
- (void)sendSticker:(NSMutableDictionary *)item Sticker:(NSString *)sticker
{
item[#"sticker"] = sticker;
NSLog(#"%#",sticker);
[self sendMessage:sticker]
}
NSLog never gets called so I know that this is not getting called. I must be missing something, after the user selects the sticker.
Sticker.h
#protocol StickersDelegate
- (void)didSelectSticker:(NSString *)sticker;
#end
#interface StickersView : UIViewController <UICollectionViewDataSource, UICollectionViewDelegate>
#property (nonatomic, assign) IBOutlet id<StickersDelegate>delegate;
#end
I see a couple of potential problem areas, but nothing definitive. I'd check the following either using a debugger or by adding additional logging:
What's the actual numerical value of indexPath.item? Does it represent a "valid" index into your array stickers2?
What is the value of file after you look it up? Is it a valid string, and does it correctly represent the name of an actual file on your file system?
What does the Outgoing class expect for the value of text in its -send:Video:Picture:Audio: method, a fully-qualified path name, or just a simple file name with no path? If the former, you'll either need to look up the system directory and construct the full file path before passing it in, or it would have needed to be constructed that way originally and inserted as such into stickers2, and if the latter, I'm assuming you will have needed to provided a "base" directory to Firebase/Parse somewhere.
This line is suspicious:
NSString *sticker = [file stringByReplacingOccurrencesOfString:#"#2x.png" withString:#""];
Do you mean to strip off the extension entirely? In other words, if you have a base filename of "foo#2x.png", then this will change "foo#2x.png" to "foo", is that what you really want. I'm guessing you might want this to be "foo.png" instead:
NSString *sticker = [file stringByReplacingOccurrencesOfString:#"#2x.png" withString:#".png"];
?
Hope this helps you track it down.

Xcode IOS Create 3 buttons to replace keyboard and text box

I am using an app to lock, unlock, and open the trunk of my car. The only problem is that I can't figure out how to modify the Xcode project so there are 3 buttons. Basically right now if I type "U" then enter- the car unlocks, "L" then enter- the car locks, and "T" then enter- the trunk opens. I want to add three buttons that simulate these three things and eliminate the typing all together. If you want to see my adruino or xcode project code I can upload those. I have put some code about the text box below.
BOOL)textFieldShouldReturn:(UITextField *)textField
{
NSString *text = textField.text;
NSNumber *form = [NSNumber numberWithBool:NO];
NSString *s;
NSData *d;
if (text.length > 16)
s = [text substringToIndex:16];
else
s = text;
d = [s dataUsingEncoding:NSUTF8StringEncoding];
if (bleShield.activePeripheral.state == CBPeripheralStateConnected) {
[bleShield write:d];
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:text, TEXT_STR, form, FORM, nil];
[tableData addObject:dict];
[_tableView setContentOffset:CGPointMake(0, CGFLOAT_MAX)];
NSLog(#"%f", _tableView.contentOffset.y);
[self.tableView reloadData];
}
textField.text = #"";
return YES;
Thanks for the help!
Your view controller probably has a textFieldShouldReturn method which is taking the string value from the text field and building a parameter to a call that initiates sending the command. If not this method then perhaps its action method linked to the text field.
You'll need to duplicate parts of that code into a method that receives a string parameter instead of taking it from the text field, say named sendLockCommand:(NSString *)commandString (assuming you're coding in Objective-C, also like that repo).
Make action methods for your buttons, something like lockDoors, unlockDoors, openTrunk, in each call [self sendLockCommand:#"L"], each with the appropriate string. Wire up the buttons to those actions and you're good to go.

Correctly casting info.plist entries to NS* types

I want to write a helper class to get values from my info.plist and have them be cast to their correct type. So, if I try to access a property that's actually a number as a date, I should get back nil or an error.
I'm having trouble coming up with a nice way to check the type. I've tried to read [val class]. In the example below, it comes back as __NSTaggedDate for date values, which seems like an implementation detail I don't want to rely on.
- (NSDate *)dateConfig:(NSString *)name
{
_configs = [[NSBundle mainBundle] objectForInfoDictionaryKey:#"myConfigDictionary"];
id val = [_configs objectForKey:name];
// TODO how do I tell?
if([val class] != ???)
{
return nil;
}
return val;
}
I want to do this reliably for all other plist types as well. What's an elegant way to get this done?
You are looking for the message isKindOfClass:
if([val isKindOfClass:[NSNumber class]])
{
return (NSNumber *)val;
}
else
{
return nil;
}
Be aware that there is also isMemberOfClass: but you rarely would want this. Many foundation objects are really Core Foundation based (i.e. NSString is NSCFString most of the time).

Getting two sender values instead of one for particular case?

I am having a IBAction for 4 buttons which represent 4 available answers and each time I press a button I read the sender ID, then it figures out if answer is correct and so on.
Now I have a special case, when another button (nothing in common with those 4 buttons) is pressed, it waits for two of these answers, checks if one of them is correct( i know how to do that) and then the program continues running.
So for now, I have :
- (IBAction)answerButtonPressed:(id)sender {
NSString* answer= [[sender titleLabel] text];
//checks if answer key is equal to a1 ( which is always the correct answer )
if([[currentQuestionUsefulVariable valueForKey:#"a1"] isEqualToString:answer] ){
correctQuestionsCount1 ++;
}
//answer is wrong
else{
wrongQuestionsCount1 ++;
}
}
As you see I store the answer string in a variable called answer
And again - All I need is to store two answers and check the two of them when this special button is pressed. I will of course put a boolean variable to indicate when it is pressed and it will do the work.
EDIT:
The two answer thing is when I press a specific joker button and it gives the advantage to the user to chose two of four available answers. This is why I need to do that. For any other cases I need only one answer at a time.
Any ideas ?
Well you're going to need an instance variable, the value of which persists throughout the lifetime of the object, and perhaps using a mutable array of the answers is the way forward:
#interface MyViewController ()
{
NSMutableArray *_correctAnswers;
}
It must be initialised in viewDidLoad (other options are available):
-(void)viewDidLoad {
[super viewDidLoad];
_correctAnswers = [NSMutableArray new];
}
and then start collecting correct answers into this array:
- (IBAction)answerButtonPressed:(id)sender {
NSString* answer= [[sender titleLabel] text];
//checks if answer key is equal to a1 ( which is always the correct answer )
if([[currentQuestionUsefulVariable valueForKey:#"a1"] isEqualToString:answer] ){
[_correctAnswers addObject:answer];
}
//answer is wrong
else{
wrongQuestionsCount1 ++;
}
if ([_correctAnswers count] == 2) {
// Do something? It's not exactly clear what you want to do
// when 2 correct answers have been given.
}
}
Note: you can dump correctQuestionsCount1 as that will be [_correctAnswers count] now. Also you will need to reset the array at some point.
Note 2: You could also start collecting incorrect answers as well, for some analysis or perhaps to disable that button so the user cannot repeatedly answer the question wrong.

Comparing NSString to UITextField text never gets called

I record the value of the text in my UITextField and I want to compare the text to the original text field value later. I try something like this, but I never get the NSLog to be displayed. Any ideas why?
defaultTopicText = topicTextField.text;
if ([topicTextField.text isEqualToString:defaultTopicText]){
NSLog(#"YES");
}else{
NSLog(topicTextField.text);
NSLog(defaultTopicText);
}
The code looks exactly like you see it. The first line I assign the value and the other - I compare with it. And it's not being called.
EDIT:
The code itself IS getting called and I also get the same values when I put them in NSLog. Might the problem be that the text field contains #"\n" characters?
NSLog gives me this:
2013-03-18 20:45:22.037 myapp[524:907]
Here comes the text
2013-03-18 20:45:22.039 myapp[524:907]
Here comes the text
Try to print out the value of the topicTextField.text and see what is shows. otherwise set the breakpoints to see if you are reaching to that particular line of code.
You coud also try comparing after removing the white spaces and new line, if there might be any
NSString *trimmmedText = [topicTextField.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
if ([trimmmedText isEqualToString:defaultTopicText]){
NSLog(#"YES");
}
Try changing to this:
NSString *newString = [defaultTopicText stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
if ([newString isEqualToString:defaultTopicText]){
NSLog(#"YES");
}
I typed the following the figured out the answer...
running this should give you your answer:
if(!defaultTopicText){
NSLog(#"defaultTopicText is nil");
}else{
NSLog(#"defaultTopicText is a: %#".[defaultTopicText classname]);
}
defaultTopicText = topicTextField.text;
if ([topicTextField.text localizedCaseInsensitiveCompare:defaultTopicText] == NSOrderedSame){
NSLog(#"YES");
}else{
NSLog(#"\"%#\" != \"%#\"",defaultTopicText, topicTextField.text);
}
Then I realized: topicTextField.text can only not be the same object as itself using this comparison method if it is nil.
topicTextField.text has to be nil... so it ends up executing:
id var = nil;
[var isEqual:nil];
and the runtime makes that return 0;
... so fix your outlet to topicTextField

Resources