I use NSNotification to send notification when switch is changed position to start updating annotations on map. My problem is that I have 8 switches and when user change position of few switches, map updates for many times. How a limit that to just one notification?
- (IBAction)saveSwitch:(id)sender
{
[[NSNotificationCenter defaultCenter] postNotificationName:#"MyAppSettingsChanged" object:self userInfo:nil];
NSUserDefaults *defs1 = [NSUserDefaults standardUserDefaults];
[defs1 setBool: blackSwitch.on forKey: #"blackKey"];
NSUserDefaults *defs2 = [NSUserDefaults standardUserDefaults];
[defs2 setBool: greenSwitch.on forKey: #"greenKey"];
NSUserDefaults *defs3 = [NSUserDefaults standardUserDefaults];
[defs3 setBool: purpleSwitch.on forKey: #"purpleKey"];
NSUserDefaults *defs4 = [NSUserDefaults standardUserDefaults];
[defs4 setBool: orangeSwitch.on forKey: #"orangeKey"];
NSUserDefaults *defs5 = [NSUserDefaults standardUserDefaults];
[defs5 setBool: blueSwitch.on forKey: #"blueKey"];
NSUserDefaults *defs6 = [NSUserDefaults standardUserDefaults];
[defs6 setBool: redSwitch.on forKey: #"redKey"];
NSUserDefaults *defs7 = [NSUserDefaults standardUserDefaults];
[defs7 setBool: darkblueSwitch.on forKey: #"darkblueKey"];
NSUserDefaults *defs8 = [NSUserDefaults standardUserDefaults];
[defs8 setBool: yellowSwitch.on forKey: #"yellowKey"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
In another view
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(onAppSettingsChanged:) name:#"MyAppSettingsChanged" object:nil];
}
Updating annotations
- (void) onAppSettingsChanged:(NSNotification *)notification {
NSLog(#"Settings was changed");
//Create the thread
[NSThread detachNewThreadSelector:#selector(loadPList) toTarget:self withObject:nil];
}
You must update some BOOLean value to indicate that you are not currently processing an update, and proceed accordingly. I.E.
- (void) onAppSettingsChanged:(NSNotification *)notification {
NSLog(#"Settings was changed");
if (!myBoolToIndicateProcessing) {
//Create the thread
myBoolToIndicateProcessing = YES;
[NSThread detachNewThreadSelector:#selector(loadPList) toTarget:self withObject:nil];
}
}
Then, when the reload has finished, set the BOOL back to NO.
Related
I basically have two switch buttons that i want the user to select from either two player or group play. However i dont want the user to be able to select both of these so idealy when the user clicks one the other turns off. How would be best to implement this?
-(void)stateSwitchedtwoplayer:(id)sender {
UISwitch *tswitch = (UISwitch *)sender;
NSUserDefaults *defaults =[NSUserDefaults standardUserDefaults];
[defaults setObject: tswitch.isOn ? #"YES" : #"NO" forKey:#"twoplayerswitch"];
[defaults synchronize];
}
-(void)stateSwitchedgroup:(id)sender {
UISwitch *tswitch = (UISwitch *)sender;
NSUserDefaults *defaults =[NSUserDefaults standardUserDefaults];
[defaults setObject: tswitch.isOn ? #"YES" : #"NO" forKey:#"groupswitch"];
[defaults synchronize];
}
Do you have references for both switches ?
If yes, it will be something like this :
-(void)stateSwitchedtwoplayer:(id)sender {
UISwitch *tswitch = (UISwitch *)sender;
self.switchGroup.on =! tswitch.isOn; //reference to group switch
NSUserDefaults *defaults =[NSUserDefaults standardUserDefaults];
[defaults setBool: tswitch.isOn forKey:#"twoplayerswitch"];
[defaults setBool: !tswitch.isOn forKey:#"groupswitch"];
[defaults synchronize];
}
-(void)stateSwitchedgroup:(id)sender {
UISwitch *tswitch = (UISwitch *)sender;
self.switchTwoPlayer.on =! tswitch.isOn; //reference to two players switch
NSUserDefaults *defaults =[NSUserDefaults standardUserDefaults];
[defaults setBool: tswitch.isOn forKey:#"groupswitch"];
[defaults setBool: tswitch.isOn forKey:#"twoplayerswitch"];
[defaults synchronize];
}
but if you want that both switches can be off, then you just need to change it on
self.switchGroup.on =! tswitch.isOn == YES; //reference to group switch
self.switchTwoPlayer.on =! tswitch.isOn == YES; //reference to two players switch
You would implement this with KVO. You can find documentation at: https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/KeyValueObserving/Articles/KVOCompliance.html. But i would suggest you not to.
You should implement some UISegmentedControl for these type of operations. Why don't you take a look at: https://developer.apple.com/library/ios/documentation/uikit/reference/UISegmentedControl_Class/Reference/UISegmentedControl.html.
I have 4 ui switches on one view controller and two are working perfect however the last two have setup so you can only click on either group or two player however when you click on two player on then click save and go back in it turns both switches on however if you do the same in group it dosnt not do this?
Anyone see what im doing wrong here?
-(void)stateSwitched:(id)sender {
UISwitch *tswitch = (UISwitch *)sender;
NSUserDefaults *defaults =[NSUserDefaults standardUserDefaults];
[defaults setObject: tswitch.isOn ? #"YES" : #"NO" forKey:#"truthonoff"];
[defaults synchronize];
}
-(void)stateSwitcheddare:(id)sender {
UISwitch *tswitch = (UISwitch *)sender;
NSUserDefaults *defaults =[NSUserDefaults standardUserDefaults];
[defaults setBool: tswitch.isOn forKey:#"groupswitch"];
[defaults setBool: tswitch.isOn forKey:#"twoplayerswitch"];
[defaults synchronize];
}
-(void)stateSwitchedtwoplayer:(id)sender {
UISwitch *tswitch = (UISwitch *)sender;
//turns two player off when on and soforth
self.groupswitch.on =! tswitch.isOn;
NSUserDefaults *defaults =[NSUserDefaults standardUserDefaults];
[defaults setBool: tswitch.isOn forKey:#"twoplayerswitch"];
[defaults setBool: !tswitch.isOn forKey:#"groupswitch"];
[defaults synchronize];
}
-(void)stateSwitchedgroup:(id)sender {
UISwitch *tswitch = (UISwitch *)sender;
//turns two player off when on and soforth
self.twoplayerswitch.on =! tswitch.isOn;
NSUserDefaults *defaults =[NSUserDefaults standardUserDefaults];
[defaults setBool: tswitch.isOn forKey:#"groupswitch"];
[defaults setBool: tswitch.isOn forKey:#"twoplayerswitch"];
[defaults synchronize];
}
just realised im running this on viewdidload which may be affecting it?
[self.twoplayerswitch setOn:[[defaults objectForKey:#"twoplayerswitch"] boolValue] animated:YES];
[self.twoplayerswitch addTarget:self action:#selector(stateSwitchedtwoplayer:) forControlEvents:UIControlEventValueChanged];
[self.groupswitch setOn:[[defaults objectForKey:#"groupswitch"] boolValue] animated:YES];
[self.groupswitch addTarget:self action:#selector(stateSwitchedgroup:) forControlEvents:UIControlEventValueChanged];
In the stateSwitchedtwoplayer method, you potentially change the state of self.groupswitch.on, but you don't save the change to NSUserDefaults.
I have managed to change the state of my UISwitch and save to NSUserDefaults.
My UISwitch is in a different view from the main view and when I flip between views, my UISwitch button always appears ON even though the state may be OFF.
- (IBAction)truthonoff:(id)sender {
if(_truthonoff.on) {
// lights on
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setValue:#"yes" forKey:#"truthonoff"];
[defaults synchronize];
self.status.text = #"on";
}
else {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setValue:#"no" forKey:#"truthonoff"];
[defaults synchronize];
self.status.text =#"off";
}
}
And this is how I'm loading the button in the second view controller:
NSUserDefaults *defaults =[NSUserDefaults standardUserDefaults];
self.text.text=[defaults objectForKey:#"truthonoff"];
How can I ensure the UISwitch state represents the value in the NSUserDefaults (i.e. when it's OFF it shows as OFF and when ON shows as ON)?
Try this:
NSUserDefaults *defaults =[NSUserDefaults standardUserDefaults];
[self.valueSwitch setOn:[[defaults objectForKey:#"truthonoff"] boolValue] animated:YES];
[self.valueSwitch addTarget:self action:#selector(stateSwitched:) forControlEvents:UIControlEventValueChanged];
In stateSwitched do this:
-(void)stateSwitched:(id)sender {
UISwitch *tswitch = (UISwitch *)sender;
NSUserDefaults *defaults =[NSUserDefaults standardUserDefaults];
[defaults setObject: tswitch.isOn ? #"YES" : #"NO" forKey:#"truthonoff"];
[defaults synchronize];
}
Hope this helps .. :)
A little too late but Instead of doing like the answer you have accepted:
NSUserDefaults *defaults =[NSUserDefaults standardUserDefaults];
[defaults setObject: tswitch.isOn ? #"YES" : #"NO" forKey:#"truthonoff"];
[defaults synchronize];
the right way would be:
NSUserDefaults *defaults =[NSUserDefaults standardUserDefaults];
[defaults setBool:tswitch.isOn forKey:#"truthonoff"];
[defaults synchronize];
This save you from checking the value of the boolean, since NSUserDefaults can take boolean value.
Also it would be easier to retrieve the boolean:
bool truthonoff = [defaults boolForKey:#"truthonoff"];
Read up some more on boolForKey
Connect your your UISwitch to an IBOutlet in your ViewController.
You can (un-)set the switch with:
[mySwitch setOn:TRUE animated:TRUE];
Method Reference
I have an NSMutableArray inside of my AppDelegate, and I'm attempting to save it to NSUserDefaults. The NSMutableArray (strainsfinal) contains a list of favorited items. I want this list to save, and be present even if the app is shut down, and then restarted. Does anyone know why my code isn't working (not saving my data)? See below:
AppDelegate.m
-(void)updateStrains:(NSDictionary *)item
{
NSUserDefaults *currentDefaults = [NSUserDefaults standardUserDefaults];
NSData *dataSave = [currentDefaults objectForKey:#"strains"];
if (strainsfinal != nil)
{
NSArray *oldSavedArray = [NSKeyedUnarchiver unarchiveObjectWithData:dataSave];
if (oldSavedArray != nil)
strainsfinal = [[NSMutableArray alloc] initWithArray:oldSavedArray];
else
strainsfinal = [[NSMutableArray alloc] init];
}
}
EDIT: Appdelegate.m So I've changed my above method to the method below (and I thought it should work), but the app crashes, saying: "Terminating app due to uncaught exception 'NSInvalidArguementException', reason: 'NSConcreteAttributedString initwithString: nil 'value'.
What am I missing?!
-(void)updateStrains:(NSDictionary *)item {
NSData *dataSave = [NSKeyedArchiver archivedDataWithRootObject:strainsfinal];
[[NSUserDefaults standardUserDefaults] setObject:dataSave forKey:#"strains"];
NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
[nc postNotificationName:#"arrayupdated" object:self userInfo:nil];
NSLog(#"updated strains %#",strainsfinal);
}
You must add
[currentDefaults synchronize];
each time after you save something to userDefaults;
But for such kind of data is better to use .plist files.
Check documentation for more info.
EDITED Code:
-(void)updateStrains:(NSDictionary *)item {
NSData *dataSave = [NSKeyedArchiver archivedDataWithRootObject:item[#"strainsfinal"]];
[[NSUserDefaults standardUserDefaults] setObject:dataSave forKey:#"strains"];
// NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
// [nc postNotificationName:#"arrayupdated" object:self userInfo:nil];
NSLog(#"updated strains %#",strainsfinal);
[[NSUserDefaults standardUserDefaults] synchronize]; // this will save you UserDefaults
}
use following method :
NSUserDefaults *userDef = [NSUserDefaults standardUserDefaults];
[userDef setObject:array1 forKey:#"DataArra1"];
[userDef setObject:array2 forKey:#"DataArr2"];
[userDef synchronize];
To retrieve the information:
NSUserDefaults *userDef = [NSUserDefaults standardUserDefaults];
NSArray *arrayText2 = [userDef objectForKey:#"DataArra1"];
NSArray *arrayText1 = [userDef objectForKey:#"DataArr2"];
You should archive NSArray before saving.
[[NSUserDefaults standardUserDefaults]
setObject:[NSKeyedArchiver archivedDataWithRootObject:yourArray]
forKey:#"yourArray"];
and unarchive when getting from NSUserDefaults.
NSData *data = [currentDefaults objectForKey:#"yourArray"];
if (data != nil)
{
NSArray *savedArray = [NSKeyedUnarchiver unarchiveObjectWithData:data];
}
I am working with the simulator, and I am doing something like this when the app starts to check if it was opened for the first time:
and then checking if that key/value is empty so that this code executes only once:
NSUserDefaults *standardUserDefaults = [NSUserDefaults standardUserDefaults];
if([standardUserDefaults objectForKey:#"first_time_cookie"] == nil)
{
[standardUserDefaults setBool:YES forKey:#"first_time_cookie"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
but every time I run the program, it executes again. Any idea what is going wrong here?
Just a guess: standardUserDefaults is nil?
You can do different!
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:NO], #"first_time_cookie"];
[defaults registerDefaults:dict];
if ([defaults boolForKey:#"first_time_cookie"] == NO){
[defaults setBool:YES forKey:#"first_time_cookie"];
[defaults synchronize];
}
a bool is not an object. This should work
if([standardUserDefaults boolForKey:#"first_time_cookie"] == NO)
{
[standardUserDefaults setBool:YES forKey:#"first_time_cookie"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
try using
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"first_time_cookie"] == false)
and let me know if it works,
gung-ho