Can't set NSSlider value in applicationDidFinishLaunching - objective-c

I need to set a slider in preferences window of a cocoa application.
If I set the NSSlider in awakeFromNib like so
-(void)awakeFromNib{
[thresholdSlider setInValue:9];
}
the preference window updates with the value when opened.
Though, since it is a preference window, I need to register the Value with NSUserDefault, so when the application at launch would run :
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification{
[thresholdSlider setValue:[NSUserDefaults standardUserDefaults] forKey:kthresh];
NSLog( #"%#",[thresholdSlider objectValue]);
}
But I cant even set the slider value in the applicationDidFinishLaunching method
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification{
[thresholdSlider setIntValue:9];
NSLog( #ā€œ%dā€,[thresholdSlider intValue]);}
returns 0 and slider is set to minimum value(set in IB) in the preferences window.
Where can I call the [thresholdSlider setValue:[NSUserDefaults standardUserDefaults] forKey:kthresh]; to get the slider updated with the user value on last application quit?
The code edited according to Vadian proposition :
+(void)initialize{
NSDictionary *dicDefault = #{#"kthresh":#9};
[[NSUserDefaults standardUserDefaults]registerDefaults:dicDefault];}`
`- (void)applicationDidFinishLaunching:(NSNotification*)aNotification{
`//Preferences
NSInteger thresholdValue = [[NSUserDefaults standardUserDefaults] integerForKey:#"kthresh"];`
thresholdSlider.integerValue = thresholdValue;}`
`-(void)applicationWillTerminate:(NSNotification *)notification {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setInteger:thresholdSlider.integerValue forKey:#"kthresh"];
[defaults synchronize];}`

In AppDelegate as soon as possible register the key value pair with a default value. This value is always used if no custom value has been written to disk yet.
NSDictionary *defaultValues = #{#"kthresh" : #9};
[[NSUserDefaults standardUserDefaults] registerDefaults:defaultValues];
Then set the value of the slider wherever you want, consider the syntax
NSInteger thresholdValue = [[NSUserDefaults standardUserDefaults] integerForKey:#"kthresh"];
thresholdSlider.integerValue = thresholdValue;
To write the value to disk use this
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults] ;
[defaults setInteger:thresholdSlider.integerValue forKey:#"kthresh"];
[defaults synchronize];
Do not use setValue:forKey: and valueForKey: to talk to NSUserDefaults
Alternatively use Cocoa bindings and bind the key integerValue to the NSUserDefaultsController instance in Interface Builder.

[thresholdSlider setValue:[NSUserDefaults standardUserDefaults] forKey:kthresh];
should be
[thresholdSlider setObjectValue:[[NSUserDefaults standardUserDefaults] valueForKey:kthresh]];

Related

Saving NSUserDefaults Issue?

i have been working on a app, and needed to store a string. I used this code to set the default:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setValue:CertificateKey.stringValue forKey:#"SavedKey"];
[[NSUserDefaults standardUserDefaults] synchronize];
NSLog(#"%#",[defaults objectForKey:#"SavedKey"]);
I loged it, so i know it saved...well, it showed me the value.
When i open my application, I use this to retrieve the default:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[CertificateKey setStringValue:[defaults objectForKey:#"SavedKey"]];
[CertificateKey setTitleWithMnemonic:[defaults objectForKey:#"SavedKey"]];
[[NSUserDefaults standardUserDefaults] synchronize];
Why will it not get the default value? Did i not completely save it?
Don't quit the application by pressing the stop button in xcode. Instead, quit it by right clicking on the application icon and selecting "Quit".
Edit
Maybe the first time that you execute the application, you want to save some defaults but you don't want to set them the second+ time that the application runs.
For this purpose in some class initialize method register the defaults, like this:
+ (void) initialize
{
NSUserDefaults* defaults= [NSUserDefaults standardUserDefaults];
[defaults registerDefaults: #{} ];
// This case it's an empty dictionary, but you can put whatever you want inside it.
// just convert it to data if it's not an object storable to a plist file.
}
Also, you're using setValue:forKey: , that method is inherited from NSObject. Use setObject:forKey: .
And use finalize if you want to save the defaults at the end:
- (void) finalize
{
// Save the defaults here
}
You might have a problem because you are creating an instance of NSUserDefaults. From what I understand you are supposed to access it like so: [[NSUserDefaults standardUserDefaults] setValue:#"Pikachu" forKey:#"Best Pokemon Ever"]; [[NSUserDefaults standardDefaults] objectForKey:#"Best Pokemon Ever"]; Rather than actually creating an instance of it.

Trying to save and set UISwitch state with NSUserDefaults

This is supposed to save the value of two UISwitches to NSUserDefaults and then set the switches on load based on the values saved to the defaults. I've been at this for hours but I can't seem to get it to work. Any help would be greatly appreciated.
The toggles are in a View that I'm using for settings. There are only two toggles, so I want to use NSUserDefaults. Toggles default to OFF. I want to toggle to ON and have that change be saved so that I can change the User experience based on the toggle's value. Then, when the User opens the settings again, I want them to display their current saved state.
I think that the value is being saved, but it is not being applied to the Switches when I reenter the Settings View.
- (IBAction)setBeadVibratorBySwitchState:(id)sender
{
if (setBeadVibrator.selected == YES) {
NSUserDefaults *beadSettings = [NSUserDefaults standardUserDefaults];
[beadSettings setBool:NO forKey:#"beadSwitchStatus"];
[beadSettings synchronize];
}
if (setBeadVibrator.selected == NO) {
NSUserDefaults *beadSettings = [NSUserDefaults standardUserDefaults];
[beadSettings setBool:YES forKey:#"beadSwitchStatus"];
[beadSettings synchronize];
}
NSLog(#"Bead Executed");
}
- (IBAction)setDecadeVibratorBySwitchState:(id)sender
{
if (setDecadeVibrator.selected == YES) {
NSUserDefaults *decadeSettings = [NSUserDefaults standardUserDefaults];
[decadeSettings setBool:NO forKey:#"decadeSwitchStatus"];
[decadeSettings synchronize];
}
if (setDecadeVibrator.selected == NO){
NSUserDefaults *decadeSettings = [NSUserDefaults standardUserDefaults];
[decadeSettings setBool:YES forKey:#"decadeSwitchStatus"];
[decadeSettings synchronize];
}
NSLog(#"Decade Executed");
}
- (void)viewDidLoad
{
[super viewDidLoad];
setBeadVibrator.selected = [[NSUserDefaults standardUserDefaults] boolForKey:#"beadSwitchStatus"];
setDecadeVibrator.selected = [[NSUserDefaults standardUserDefaults] boolForKey:#"decadeSwitchStatus"];
}
NSUserDefaults can only store objects of type NSData, NSString, NSNumber, NSDate, NSArray, or NSDictionary. So, I suggest that you put the state of the switch in an NSString and put that string in the NSUserDefaults. Than when you retrieve the info from the NSUserDefaults, you can use an if statement to set the value of the boolean again.
If you are using UISwitch, you should set the on property, instead of selected.
setBeadVibrator.on = [[NSUserDefaults standardUserDefaults] boolForKey:#"beadSwitchStatus"];
setDecadeVibrator.on = [[NSUserDefaults standardUserDefaults] boolForKey:#"decadeSwitchStatus"];
see UISwitch Class Reference
I would suggest that you put the NSLog statements in the if-statements to see if they are really saved. If not, your UISwitches may not be configured properly with the UIControlEventValueChanged event.
You can read up more from Apple doc. Here is a very detailed website on using UISwitches.

NSUserDefaults. setValue works, Not setBool

I trying to store some settings in NSUserDefaults, but It seems that the app won't store the setBool values.
This works:
[[NSUserDefaults standardUserDefaults] setValue: #"hello" forKey: #"test"];
[[NSUserDefaults standardUserDefaults] synchronize];
When I terminate the app and restart it, the value have been saved. However, when I do this:
[[NSUserDefaults standardUserDefaults] setBool: YES forKey: #"test"];
[[NSUserDefaults standardUserDefaults] synchronize];
It won't save after I close the app and restart it.
Should I file a bug report, or is there something I'm missing here?
Thanks
Edit:
I figure what I did wrong. In AppDelegate, I wanted to check if the boolForKey was set, and it it wasn't I did this:
if (![defaults boolForKey: #"test123"])
[defaults setBool: YES forKey: #"test123"];
... however, when it comes to boolWithKey, the "!" just check if the bool is YES or NO, not if its nil.
How can you be sure its not working? I tried your code and it works for me. Are you sure you are reading the Boolean in the correct way AFTER you write it?
This code SHOULD work:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setBool:NO forKey:#"test"];
[defaults synchronize];
BOOL myBool = [defaults boolForKey:#"test"];
I had the same problem by having the following code in my AppDelegate to keep track of whether the user had seen a particular viewController to display a walkthrough, and then setting this Bool to NO after the user had seen it.
if (![standardUserDefaults boolForKey:#"firstViewOfVC"]) {
[standardUserDefaults setBool:YES forKey:#"firstViewOfVC"];
}
But then when you set it to NO later on and check if it "exists", you are actually seeing the NO boolean value and setting it back to yes. The quick fix is just to store the boolean value in an NSNumber object so that you can check for it's existence, independent of its value being YES or NO. See below:
if (![standardUserDefaults objectForKey:#"firstViewOfVC"]){
[standardUserDefaults setValue:[NSNumber numberWithBool:YES] forKey:#"firstViewOfVC"];
}
I had the exact same problem. Everything EXCEPT BOOLs were persisting correctly; but i was using some old coding styles from ios 3. recoded this way, everything works.
If anybody else is using old books.... here is an example
Bad stuff:
//////////// set / get bL2R
if (![[NSUserDefaults standardUserDefaults]
boolForKey:kL2RomanizationChoice]) {
[[NSUserDefaults standardUserDefaults]
setBool:YES
forKey:kL2RomanizationChoice];
bL2R = YES;
NSLog(#"L2Rom not found, set to YES.");
}
else {
bL2R = [[NSUserDefaults standardUserDefaults]
boolForKey:kL2RomanizationChoice];
NSLog(#"L2Rom found.");
if (bL2R) {
NSLog(#"L2Rom found to be YES.");
}
}
Good stuff:
if (![defaults boolForKey:kL2RomanizationChoice])
[defaults setBool:YES forKey:kL1RomanizationChoice];
L2String_Setting = [defaults objectForKey:kSecondLangChoice];
bL2R = [defaults boolForKey:kL2RomanizationChoice];
Update: sadly this only seemed to work briefly, and now is failing again... using Xcode 4.5.2. may just swap out bools for integers...
XCode 4.6 seems to have the same problem highlighted by hangzhouharry. A useful call is [[NSUserDefaults standardUserDefaults] dictionaryRepresentation] to see if your key values are looking the way they should.
For example -> autoLogout = 0;
which was set as a Bool, [settings boolForKey:#"autoLogout"] returns nothing
[settings integerForKey:#"autoLogout"] returns 0 (as, sort of, expected)

Show screen on first launch only in iOS

Tweetbot and Clear show's on the first start of the app a small tutorial screen how the app works. The screen with the small tutorial only pops up on the first start up of the app (1 time)
How and with what can i make a similar thing? Can anyone push me in the right direction?
View i mean:
I'm assuming by Xcode you actually mean iOS.
What you need to do is use the NSUserDefaults class to store a flag indicating whether the user has seen the tutorial screen before.
When your app first loads (or at the point you want to decide whether or not to show the tutorial screen), do something like this:
if(![[NSUserDefaults standardUserDefaults] boolForKey:#"hasSeenTutorial"])
[self displayTutorial];
This checks the saved NSUserDefaults for the current user for a value named "hasSeenTutorial", which won't exist yet. Since it doesn't exist, it will call displayTutorial. displayTutorial refers to your method for creating the tutorial view. You can figure out that part.
Then, once the user closes the tutorial screen:
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"hasSeenTutorial"];
That value will be saved for your user profile, meaning the next time it checks it, it will be true, so displayTutorial won't be called.
In your viewDidLoad:
if (![#"1" isEqualToString:[[NSUserDefaults standardUserDefaults]
objectForKey:#"aValue"]]) {
[[NSUserDefaults standardUserDefaults] setValue:#"1" forKey:#"aValue"];
[[NSUserDefaults standardUserDefaults] synchronize];
//Action here
}
Certainly, if we would like to tell user something about features after update (not only app launched first time), the solution below could be suitable.
In your viewDidLoad:
NSString *currentBundleVersion = [[NSBundle mainBundle] objectForInfoDictionaryKey:#"CFBundleVersion"];
NSString *previousBundleVersion = [[NSUserDefaults standardUserDefaults] objectForKey:#"PreviousBundleVersion"];
if (![currentBundleVersion isEqualToString:previousBundleVersion] ) {
// Here you can initialize your introduction view and present it!
}
Once the user closes the intro:
NSString *currentBundleVersion = [[NSBundle mainBundle] objectForInfoDictionaryKey:#"CFBundleVersion"];
NSUserDefaults *standardUserDefaults = [NSUserDefaults standardUserDefaults];
if (standardUserDefaults) {
[standardUserDefaults setObject:currentBundleVersion forKey:#"PreviousBundleVersion"];
[standardUserDefaults synchronize];
}
In this case app bundle version stored in your standardUserDefaults will be differ from current bundle version only after update and shown only once as well as at first launch.
Initialise your user defaults with a BOOL, something called instructionsSeen (or whatever you want) and set it to NO in your App delegate's initialize method.. In your app, test this value and if it is NO display your tutorial screen. As part of showing and displaying this screen, set the instructionsSeen to YES and store it in your defaults.
This way the demo screen will only show on first launch, unless the user uninstalls and installs the app again.
You could also show the demo for a small number of launches (say 3). In this case, don't use BOOL use a number and increment it instead.
Xamarin.iOS Version within AppDelegate:
UIStoryboard storyboard = UIStoryboard.FromName("Main", null);
if (NSUserDefaults.StandardUserDefaults.BoolForKey ("hasSeenTutorial") == false) {
UIViewController vc = storyboard.InstantiateViewController ("StartPageViewController");
this.Window.RootViewController = vc;
} else {
UIViewController vc = storyboard.InstantiateViewController ("NonStartPageViewController");
this.Window.RootViewController = vc;
}
this.Window.MakeKeyAndVisible ();
In my StartPageViewController, I have a button which sets NSUserDefaults to true, so the next time it runs, it will start off with the NonStartPageViewController:
partial void RegisterButton_TouchUpInside (UIButton sender)
{
NSUserDefaults.StandardUserDefaults.SetBool(true,"hasSeenTutorial");
NSUserDefaults.StandardUserDefaults.Synchronize();
}
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if (![defaults objectForKey:#"firstRun"]) {
[defaults setObject:[NSDate date] forKey:#"firstRun"];
[self displayTutorial];
}
Swift version :
if !(NSUserDefaults.standardUserDefaults().boolForKey("seenTutorial")) {
//Tutorial part
NSUserDefaults.standardUserDefaults().setBool(true, forKey: "seenTutorial")
}
Everyone is making this more complex and vauge than it needs to be... Simple complete solution.
In the ViewDidLoad:
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"FirstLoadKey"]) {
self.imageView.hidden = YES;
}else{
self.imageView.hidden = NO;
[[NSUserDefaults standardUserDefaults]setBool:YES forKey:#"FirstLoadKey"];
[[NSUserDefaults standardUserDefaults]synchronize];
}

problem with loading from NSUserDefaults, obj-c

I'm having a problem with NSUserDefaults. I'm saving a name, then trying to access it later in the code from another view controller, but it seems that my key is empty or not saved as when I display the string from the key my label is blank.
-(void) saveName {
NSString *name = nameField.text;
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:name forKey:#"playersName"];
[defaults synchronize];
}
-(void) viewDidLoad // method called later on in code from different viewcontroller
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *name = [defaults objectForKey:#"playersName"];
playerName.text = name; // player name == myLabel
if ([[NSUsersDefaults standardUserDefaults] objectForKey:#"playersName"] == nil) {
playerName.text =#" blank";
}
}
My string doesn't seem to be saving to userdefaults as the #"blank" string keeps showing up with my label. I'm not too familiar with NSUserDefaults so any help is much appreciated.
A few things to note when using NSUserDefaults:
calls to syncrhonize method is not necesary and will only make it slower if your program is multi threaded.
Check if the key that you use is being used by other libraries in your project
Check if the value that you set to the key is not nil
Try to use stringForKey: or boolForKey: instead of objectForKey:
I had troubles a few times with NSUserDefaults but in the end it's usually my code that's problematic.
I would suggest you to check whether your '(void) saveName' method is being called or not... Put some breakpoint and see the result