Crash interacting with NSUserDefaults and NSArray - ios

I have an NSMutableArray in which I am adding objective and storing in user defaults, but while adding it is crashing.
if ([[NSUserDefaults standardUserDefaults] objectForKey:#"bssidObserverArray"]) {
bssidObserverArray = [[NSUserDefaults standardUserDefaults] objectForKey:#"bssidObserverArray"];
}
if (bssidObserverArray.count > 0) {
if (![bssidObserverArray containsObject:vendorID]) {
NSLog(#"bssidObserverArray %#",bssidObserverArray);
// In this line app is getting crashed
[bssidObserverArray addObject:vendorID];
[[NSUserDefaults standardUserDefaults] setObject:bssidObserverArray forKey:#"bssidObserverArray"];
}
}else{
[bssidObserverArray addObject:vendorID];
[[NSUserDefaults standardUserDefaults] setObject:bssidObserverArray forKey:#"bssidObserverArray"];
}
Any suggestions would be more helpful.

Assuming bssidObserverArray is NSMutable array then come the problem here .
if ([[NSUserDefaults standardUserDefaults] objectForKey:#"bssidObserverArray"]) {
bssidObserverArray = [[NSUserDefaults standardUserDefaults] objectForKey:#"bssidObserverArray"];
}
since NSUserdefaults returns immutable. you can do like this
if ([[NSUserDefaults standardUserDefaults] objectForKey:#"bssidObserverArray"]) {
NSArray *someArray = [[NSUserDefaults standardUserDefaults] objectForKey:#"bssidObserverArray"];
bssidObserverArray = [someArray mutableCopy];
}

Related

NSMutableArray unknown after initialization

I am trying to initialize an NSMutableArray depending on if one exists in NSUserDefaults or not using and if/else statement.
if ([[NSUserDefaults standardUserDefaults] arrayForKey:#"customers"] == nil) {
NSMutableArray *customers = [NSMutableArray arrayWithCapacity:10];
} else {
NSMutableArray *customers = [[[NSUserDefaults standardUserDefaults] arrayForKey:#"customers"]mutableCopy];
}
Customer *c = [[Customer alloc]init];
c.fName = self.fnameTextField.text;
c.lName = self.lnameTextField.text;
c.username = self.usernameTextField.text;
c.balance = [self.depositTextField.text floatValue];
[customers addObject:c];
[[NSUserDefaults standardUserDefaults] setObject:customers forKey:#"customers"];
[[NSUserDefaults standardUserDefaults] synchronize];
When trying to add an object to the array, I get "Unknown receiver 'customers.'" I'm not sure why I'm not able to use the array.
Try declaring the customers array outside your if statement
NSMutableArray *customers;
if ([[NSUserDefaults standardUserDefaults] arrayForKey:#"customers"] == nil) {
customers = [NSMutableArray arrayWithCapacity:10];
} else {
customers = [[[NSUserDefaults standardUserDefaults] arrayForKey:#"customers"]mutableCopy];
}
I am quite sure you have written it like this,
NSMutableArray *customers;
if ([[NSUserDefaults standardUserDefaults] arrayForKey:#"customers"] == nil) {
NSMutableArray *customers = [NSMutableArray arrayWithCapacity:10];
} else {
NSMutableArray *customers = [[[NSUserDefaults standardUserDefaults] arrayForKey:#"customers"]mutableCopy];
}
So, what is wrong here?
Note that if and else create their own scope, so the variable you declare inside if and else are new variable, not the one from outer scope. If you want to use customers from outer scope, do it like this,
NSMutableArray *customers;
if ([[NSUserDefaults standardUserDefaults] arrayForKey:#"customers"] == nil) {
customers = [NSMutableArray arrayWithCapacity:10];
} else {
customers = [[[NSUserDefaults standardUserDefaults] arrayForKey:#"customers"] mutableCopy];
}
Now, customers inside if and else block is the same variable that you have declared outside the if/else block.

How to set again user default for dictionary

HOW To set user default again to dictionary.
Create the dictionary object and set value to it.
NSMutableDictionary * loginDictionary = [[NSMutableDictionary alloc] init];
[loginDictionary setValue:#"My Address" forKey:#"ADDRESS_KEY"];
[loginDictionary setValue:#"1234567890" forKey:#"PHONE_KEY"];
[[NSUserDefaults standardUserDefaults] setObject:newDictionary forKey:#"INFO_KEY"];
[[NSUserDefaults standardUserDefaults] synchronize];
Now I asses those dictionary value and assign to some other object.
NSDictionary *RetrievedDictionary = [[NSUserDefaults standardUserDefaults] dictionaryForKey:#"INFO_KEY"];
txt_Address.text = [RetrievedDictionary objectForKey:#"ADDRESS_KEY"];
txt_Mobile.text = [RetrievedDictionary objectForKey:#"PHONE_KEY"];
How to update?
This is what I try.
[[NSUserDefaults standardUserDefaults] setObject:#"Changed Address" forKey:#"ADDRESS_KEY"];
[[NSUserDefaults standardUserDefaults] setObject:#"0987654321" forKey:#"PHONE_KEY"];
[[NSUserDefaults standardUserDefaults] synchronize];
Its not working for me, Need your small suggestion what i am doing wrong.
#Thanks In Advance.
NSMutableDictionary* changedDictionary = [NSMutableDictionary dictionaryWithDictionary:[[NSUserDefaults standardUserDefaults] dictionaryForKey:#"INFO_KEY"]];
[changedDictionary setObject:#"Changed Address" forKey:#"ADDRESS_KEY"];
[changedDictionary setObject:#"0987654321" forKey:#"PHONE_KEY"];
[[NSUserDefaults standardUserDefaults] setObject:changedDictionary forKey:#"INFO_KEY"];
[[NSUserDefaults standardUserDefaults] synchronize];
How about this?
NSMutableDictionary *changedDictionary = [[[NSUserDefaults standardUserDefaults] dictionaryForKey:#"INFO_KEY"] mutableCopy];
[changedDictionary setObject:txt_Address.text forKey:#"ADDRESS_KEY"];
[changedDictionary setObject:txt_Mobile.text forKey:#"PHONE_KEY"];
[[NSUserDefaults standardUserDefaults] setObject:changedDictionary forKey:#"INFO_KEY"];
[[NSUserDefaults standardUserDefaults] synchronize];
NSMutableDictionary * loginDictionary = [[NSMutableDictionary alloc] init];
[loginDictionary setValue:#"My Address" forKey:#"ADDRESS_KEY"];
[loginDictionary setValue:#"1234567890" forKey:#"PHONE_KEY"];
[[NSUserDefaults standardUserDefaults] setObject:newDictionary forKey:#"INFO_KEY"];
[[NSUserDefaults standardUserDefaults] synchronize];
Your are creating loginDictionary, but adding newDictionary to the NSUserDefaults. Also I would suggest to use constant keys.

NSUserDefaults can't update a nsmutable array

I saved a nsmutableArray inside a NSUserDefaults.
In the following case, it seems that all the elements from the array are equal to 0, even though in this case position 1 and position 5 should have 1 instead of 0 as a value. I know that NSUserDefaults elements are immutable but ...I did add that mutableCopy when retrieving the value.
Where am I wrong?
//create array
NSMutableArray *objArray = [[NSMutableArray alloc] init];
for (int i=0; i< 100;i++) [objArray addObject:#"0"];
[objArray replaceObjectAtIndex:1 withObject:#"1"];
[[NSUserDefaults standardUserDefaults] setObject:objArray forKey:name];
// update
elementPosition = 5;
NSMutableArray *objArray = [[NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:name]] mutableCopy];
[objArray replaceObjectAtIndex:elementPosition withObject:#"1"];
//check the array
NSMutableArray *objArray = [NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:nameFile]];
BOOL displayContent = true;
for (int i=0; i<[objArray count];i++)
{
if ([[objArray objectAtIndex:i] isEqualToString:#"0"])
{
displayContent = false;
}
}
I think when you retrieve and your mutable array from UserDefault and updated but you didn't set that new updated object to UserDefault, its having the old object which was set before. you have to store your update array again to userdefault with same key which update your UserDefautlt.
elementPosition = 5;
NSMutableArray *objArray = [[NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:name]] mutableCopy];
[objArray replaceObjectAtIndex:elementPosition withObject:#"1"];
[[NSUserDefaults standardUserDefaults] setObject:objArray forKey:name];
You should call the synchronize method
[[NSUserDefaults standardUserDefaults] synchronize];
I think you should fix your code follow my bellow code:
[[NSUserDefaults standardUserDefaults] setObject:objArray forKey:name];
[[NSUserDefaults standardUserDefaults] synchronize];
...
NSMutableArray *objArray = [[NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:name]] mutableCopy];
[objArray replaceObjectAtIndex:elementPosition withObject:#"1"];
[[NSUserDefaults standardUserDefaults] setObject:objArray forKey:nameFile];
[[NSUserDefaults standardUserDefaults] synchronize];
Replace your code with this:
//create array
NSMutableArray *objArray = [[NSMutableArray alloc] init];
for (int i=0; i< 100;i++){
[objArray addObject:#"0"];
}
[objArray replaceObjectAtIndex:1 withObject:#"1"];
[[NSUserDefaults standardUserDefaults] setObject:objArray forKey:name];
//First mistake. Missing this. Without this line the data is not saved in NSUserDefaults
[[NSUserDefaults standardUserDefaults] synchronize];
// update
elementPosition = 5;
NSMutableArray *objArray = [[NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:name]] mutableCopy];
[objArray replaceObjectAtIndex:elementPosition withObject:#"1"];
//Second Mistake. You did not update the NSUserDefaults again.
[[NSUserDefaults standardUserDefaults] setObject:objArray forKey:name];
[[NSUserDefaults standardUserDefaults] synchronize];
//check the array
NSMutableArray *objArray = [NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:name]];
BOOL displayContent = true;
for (int i=0; i<[objArray count];i++)
{
if ([[objArray objectAtIndex:i] isEqualToString:#"0"])
{
displayContent = false;
}
//Third mistake. Once the BOOL is made false in an if block you have to make it true in the else block, otherwise the value of the BOOL will remain false even if it does not enter the if block.
else{
displayContent = true;
}
NsLog(#"ArrayIndex=[%d];DisplayContent=[%d]",i,displayContent);
}
Happy coding.

GMSGeocoder - how to set response language

When using my app in a foreign country, the google GMSGeocoder is returning the response in local language automatically. how can I set it to always return the the response in English?
Im using GMS SDK 1.7 and my code is something like this:
GMSGeocoder *geoCoder = [[GMSGeocoder alloc] init];
[geoCoder reverseGeocodeCoordinate:self.cellLocation.coordinate completionHandler:^(GMSReverseGeocodeResponse *respones, NSError *err) {
if([respones firstResult]) {
GMSAddress* address = [respones firstResult];
NSString* fullAddress = [NSString stringWithFormat:#"%#, %#",address.thoroughfare, address.locality];
self.theTextField.text = fullAddress;
} else {
self.theTextField.text = #"";
}
}];
Using a GMSGeocoder category can solve this issue, inspired by #DaNLtR
After that , It can set geocoder result as English .
#implementation GMSGeocoder (Load)
+(void)load {
[[self class] setUserLanguage:#"en-CN"];// set your wanted language.
NSLog(#"GMSGeocoder + load!");
}
- (void)dealloc {
[[self class] resetSystemLanguage];
NSLog(#"GMSGeocoder + dealloc!");
}
+ (void)setUserLanguage:(NSString *)userLanguage
{
if (!userLanguage.length) {
[[self class] resetSystemLanguage];
return;
}
[[NSUserDefaults standardUserDefaults] setValue:userLanguage forKey:#"UserLanguage"];
[[NSUserDefaults standardUserDefaults] setValue:#[userLanguage] forKey:#"AppleLanguages"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
+ (void)resetSystemLanguage
{
[[NSUserDefaults standardUserDefaults] removeObjectForKey:#"UserLanguage"];
[[NSUserDefaults standardUserDefaults] setValue:nil forKey:#"AppleLanguages"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
#end
Why should in category?
A:I tested setLanguage: before GMSGeocoder reverseGeocodeCoordinate method, it can't affect geocoder result. After I saw DaNLtR's answer , I think we can setLanguge in load method.
Why should reset language?
A:Avoide affect other module or framework .
Just change it to your language parameters
int main(int argc, char * argv[])
{
#autoreleasepool {
//For Google Maps hebrew response
//[[NSUserDefaults standardUserDefaults] setObject:#[#"en"] forKey:#"AppleLanguages"];
[[NSUserDefaults standardUserDefaults] setObject:#[#"he",#"he-IL"] forKey:#"AppleLanguages"];
[[NSUserDefaults standardUserDefaults] synchronize];
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}

In iOS I have change the language but it shows only text not images

if ([objGlobalUser.strAppLangID isEqualToString:[#"en" uppercaseString]]) {
objGlobalUser.strLanguage =#"en";
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObjects:objGlobalUser.strLanguage, nil] forKey:#"AppleLanguages"];
[[NSUserDefaults standardUserDefaults] synchronize];
NSLog(#"preferredLang: %#", objGlobalUser.strLanguage);
} else {
objGlobalUser.strLanguage =#"ar";
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObjects:objGlobalUser.strLanguage, nil] forKey:#"AppleLanguages"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
NSString *path= [[ NSBundle mainBundle ] pathForResource:objGlobalUser.strLanguage ofType:#"lproj" ];
self.viewController = [[MyViewController alloc] initWithNibName:#"MyViewController"
bundle:[NSBundle bundleWithPath:path]];
It only shows strings not images when language change
As for me, I've done all manipulations with localization in main.m and it works fine.
Here's an example:
//Localization Language setup
typedef enum {
LLAuto = 0,
LLEnglish = 1,
LLFrench = 2,
LLJapanese = 3,
LLSpanish = 4
} TLocalizationLanguage;
static NSString * const LocalizationLanguages[] = {
#"auto", #"en", #"fr", #"ja", #"es"
};
void setupLocalizationLanguage() {
TLocalizationLanguage UsedLng = (TLocalizationLanguage) USE_LOCALIZATION_LANGUAGE;
if (UsedLng == LLAuto) {
[[NSUserDefaults standardUserDefaults] removeObjectForKey:#"AppleLanguages"];
} else {
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObjects:LocalizationLanguages[UsedLng], nil] forKey:#"AppleLanguages"];
}
[[NSUserDefaults standardUserDefaults] synchronize];
NSLog(#"Use localization language: %#", LocalizationLanguages[UsedLng]);
}
// -------------------------------------------------------------------------------
#import "AppDelegate.h"
int main(int argc, char *argv[])
{
#autoreleasepool {
setupLocalizationLanguage();
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
where USE_LOCALIZATION_LANGUAGE is an environment variable.
I hope it will be useful to you.

Resources