It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I am running into a problem whereby I am unable to retain the state of a UISwitch in my app. I think the problem is I've been trying so many different examples from different tutorials and code sources to get this working, and I'm just not seeing the complete picture.
I've set up a user preferences screen, relevant code is:
AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Trying here to check whether user has run app previously, and if not set default switch value (as defined in IB)
NSString *firstRunValue = [[NSUserDefaults standardUserDefaults] stringForKey:#"testSwitch"];
if (!firstRunValue) {
[[NSUserDefaults standardUserDefaults] setBool:NO forKey:#"testSwitch"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
return YES;
}
OptionsViewController.h
#property (weak, nonatomic) IBOutlet UISwitch *testSwitch;
OptionsViewController.m
#synthesize testSwitch;
.
.
.
- (void)viewDidLoad
{
[super viewDidLoad];
// Here's the issue - following line does NOT set switch as expected from defaults...
[testSwitch setOn:[[NSUserDefaults standardUserDefaults] boolForKey:#"testSwitch"] animated:NO];
}
.
.
.
- (IBAction)updateTest:(id)sender {
// Action called when switch is clicked to save new state, Log shows 0 or 1 as expected
[[NSUserDefaults standardUserDefaults] setBool:[sender isOn] forKey:#"testSwitch"];
NSLog(#"%#", [[NSUserDefaults standardUserDefaults]valueForKey:#"testSwitch"]);
}
.
.
.
- (IBAction)saveOptions:(id)sender {
// When user clicks "Save" and exits, I synch defaults and dump them, again output is as expected
[[NSUserDefaults standardUserDefaults] synchronize];
NSLog(#"%#", [[NSUserDefaults standardUserDefaults] dictionaryRepresentation]);
[self dismissModalViewControllerAnimated:YES];
}
If someone could let me know where I'm going wrong (in English rather than in Objective-C!) I'd appreciate it, thanks!
Try this:
NSString *firstRunValue = [[NSUserDefaults standardUserDefaults] stringForKey:#"firstRun"];
if (!firstRunValue) {
[[NSUserDefaults standardUserDefaults] setObject: #"BlaBla" forKey:#"firstRun"];
[[NSUserDefaults standardUserDefaults] setBool:NO forKey:#"testSwitch"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
Related
Im developing a reminder app.
So my client want to set a rate this application popup message, that'll come up on the 10th time user open the app.is this possible.
How can i implement this?
Can anyone help me please.Thanks in advance
You could use NSUserDefaults for this:
NSUserDefaults * userDefaults = [NSUserDefaults standardUserDefaults];
NSInteger appLaunchAmounts = [userDefaults integerForKey:#"LaunchAmounts"];
if (appLaunchAmounts == 10)
{
[self showMessage];
}
[userDefaults setInteger:appLaunchAmounts+1 forKey:#"LaunchAmounts"];
You can store that into the NSUserDefaults. Just update it in applicationDidFinishLaunching:.
You can save an integer in NSUserDefaults
- (void)setInteger:(NSInteger)value forKey:(NSString *)defaultName
Retrieve it and increment it every time the appDidFinishLaunching (or appWillEnterForeground) delegate methods is called. Probably best to use appWillEnterForeground as sometimes apps can lie in the background unterminated for days.
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
NSInteger count = [defaults integerForKey:#"LaunchCount"];
count++;
/* Do checks and review prompt */
[defaults setInteger:count forKey:#"LaunchCount"];
[defaults synchronize];
This will store a value in NSUserDefaults called 'AppLaunchCount'.
- (BOOL)application:(UIApplication *)app didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
if ([[NSUserDefaults standardUserDefaults] integerForKey:#"AppLaunchCount"])
{
[[NSUserDefaults standardUserDefaults] setInteger:([[NSUserDefaults standardUserDefaults] integerForKey:#"AppLaunchCount"] + 1) forKey:#"AppLaunchCount"];
}
else
{
[[NSUserDefaults standardUserDefaults] setInteger:1 forKey:#"AppLaunchCount"];
}
}
I have a UISwitch in my app along with one in my settings bundle with the same functionality. The UISwitch in my app however is not saving its settings properly. Can anyone see anything wrong with the code?
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Set the application defaults
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSDictionary *appDefaults = [NSDictionary dictionaryWithObject:#"No" forKey:#"isKgs"];
[defaults registerDefaults:appDefaults];
[defaults synchronize];
}
- (void)switchChanged
{
[[NSUserDefaults standardUserDefaults] setBool:unitSwitch.selected forKey:#"isKgs"];
[[NSUserDefaults standardUserDefaults] synchronize];
NSLog(#"SwitchGhanged:");
}
-(void)cellForRowAtIndexPath
{
[unitSwitch addTarget:self action:#selector(switchChanged) forControlEvents:UIControlEventValueChanged];
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"isKgs"])
{
[unitSwitch setOn:YES animated:NO];
}
}
And here is the settings bundle
[[NSUserDefaults standardUserDefaults] setBool:unitSwitch.on forKey:#"isKgs"];
Use the on property for setting.
Try using on on the UISwitch:
[[NSUserDefaults standardUserDefaults] setBool:unitSwitch.on forKey:#"isKgs"];
EDIT: No need to test as unitSwitch.on is already BOOLEAN, you can assign it directly.
Been working on some code streamlining and have realised that it would be really helpful if my app had a preferences system.
Now here's how my code works.
A method runs based upon an integer stored in NSUserDefaults
e.g.
if ([[NSUserDefaults standardUserDefaults] integerForKey:#"scifi1"] == 040){
[self spaceDown];
}
else if ([[NSUserDefaults standardUserDefaults] integerForKey:#"scifi1"] == 10040){
[self ctrldown];
[self spaceDown];
}
Now what I want to do is when I exit the view (via a specific button) is to dump the value of #"scifi1" into a new preference, say for example - an integer named #"savedscifi1"
Now I know how to save integers into NSUserDefaults,
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setInteger:VALUEHERE forKey:#"savedscifi1"];
[userDefaults synchronize];
However - I'm not sure how I can substiture in the value of scifi1 instead of (in this case) 'VALUEHERE' - can anyone help with this? I feel it's really simple but I can't help but think I'm being a bit thick...sleep deprived and approaching a deadline! I know I can't just call up #"scifi1"but beyond that....??
NSInteger value = [[NSUserDefaults standardUserDefaults] integerForKey: ...];
[[NSUserDefaults standardUserDefaults] setInteger: value forKey: ...];
I need to track the download of a certain iphone application. I tried a lot and found out that we could track it from the AppStore. But i need to track that from my application itself. So please help me to identify the method that fires when the application starts for the first time. Thanks.
There's no specific method that fires only on the 1st application launch. You can set a flag in user defaults on application start - so if the flag is not present then that will mean that application launched for the 1st time:
- (void)applicationDidFinishLaunching:(UIApplication *)application {
if (![[NSUserDefaults standardDefaults] boolForKey:#"AlreadyLaunched"]){
// First launch logic
[[NSUserDefaults standardDefaults] setBool:YES forKey:#"AlreadyLaunched"];
[[NSUserDefaults standardDefaults] synchronize];
}
...
}
But i need to track that from my application itself.
No.
But if you really want to do this you could use something like this:
BOOL hasUsedSpyWareFunctions = [[NSUserDefaults standardUserDefaults] boolForKey:#"SpyWareKey"];
if (!hasUsedSpyWareFunctions) {
[self spyOnUser];
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"SpyWareKey"];
}
if you are a Pro in spying you only set the key to YES if the method returned successfully (ie a network connection could be established)
There’s no such an event, at least not one that I know of. But what you want can be trivially done using NSUserDefaults. Simply check for some boolean flag and if it’s not there, it’s a first run and you can set the flag:
NSString *const AlreadyRunKey = #"already-run";
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
if (![prefs boolForKey:AlreadyRunKey]) {
[prefs setBool:YES forKey:AlreadyRunKey];
[prefs synchronize];
// do whatever else you want
}
I want to check if my iPhone app is running for the first time. I can create a file in the documents folder and check that file to see if this is the first time the app is running, but I wanted to know if there is a better way to do this.
I like to use NSUserDefaults to store an indication of the the first run.
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if (![defaults objectForKey:#"firstRun"])
[defaults setObject:[NSDate date] forKey:#"firstRun"];
[[NSUserDefaults standardUserDefaults] synchronize];
You can then test for it later...
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if([defaults objectForKey:#"firstRun"])
{
// do something or not...
}
Ok what confuses the hell out of me about User Defaults.
WHERE are they stored?
you dont care it varies per iOS/Mac.
you just getVALUE by KEY
setVALUE by KEY + synchronize
iOS/Mac does the rest.
This is the common use case:
Checking for the existence of a value e.g firstRun.
The first time it will NOT EXIST so usually followed by setting the value.
2nd Run
- on next loop it does exist and other use case/else stmt is triggered
---- .h
#interface MyAppDelegate : UIResponder <UIApplicationDelegate>
//flag to denote if this is first time the app is run
#property(nonatomic) BOOL firstRun;
------ .m
#implementation MyAppDelegate
#synthesize firstRun = _firstRun;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//==============
//Check to see if this is first time app is run by checking flag we set in the defaults
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if (![defaults objectForKey:#"firstRun"]){
//flag doesnt exist then this IS the first run
self.firstRun = TRUE;
//store the flag so it exists the next time the app starts
[defaults setObject:[NSDate date] forKey:#"firstRun"];
}else{
//flag does exist so this ISNT the first run
self.firstRun = FALSE;
}
//call synchronize to save default - where its saved is managed by iOS - varies by device and iOS/Mac
[[NSUserDefaults standardUserDefaults] synchronize];
//TO TEST: delete the app on the device/simulator
//run it - should be the first run
//close it - make sure you kill it and its not just in the background else didFinishLaunchingWithOptions wont be called
//just applicationDidBecomeActive
//2nd run it should self.firstRun = FALSE;
//=============
//NOTE IMPORTANT IF YOURE ROOTVIEWCONTROLLER checks appDelegate.firstRun then make sure you do the check above BEFORE setting self.window.rootViewController here
self.window.rootViewController = self.navController;
[self.window makeKeyAndVisible];
return YES;
}
---- USING THE FLAG
MyAppDelegate *appDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
if (appDelegate.firstRun){
NSLog(#"IS FIRST RUN - Do something: e.g. set up password");
}else {
NSLog(#"FPMyMusicScreenViewController: IS NOT FIRST RUN - Prompt for password");
}
The examples above confused me a bit as they show how to check for it the first time but then mention how to 'check for it later' in the same comment.
The problem is when we find it doesnt exist we immediately create it and synchronize.
So checking for it late actually mean when you RESTART THE APP not in same run as first run.
In your app delegate register a default value:
NSDictionary *defaultsDict =
[[NSDictionary alloc] initWithObjectsAndKeys:[NSNumber numberWithBool:YES], #"FirstLaunch", nil];
[[NSUserDefaults standardUserDefaults] registerDefaults:defaultsDict];
[defaultsDict release];
Then where you want to check it:
NSUserDefaults *sharedDefaults = [NSUserDefaults standardUserDefaults];
if ([sharedDefaults boolForKey:#"FirstLaunch"]) {
//Do the stuff you want to do on first launch
[sharedDefaults setBool:NO forKey:#"FirstLaunch"];
[sharedDefaults synchronize];
}
You can implement it with the static method below. I think it's better since you can call this method as many times as you like, unlike the other solutions. enjoy: (Keep in mind that it's not thread-safe)
+ (BOOL)isFirstTime{
static BOOL flag=NO;
static BOOL result;
if(!flag){
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"hasLaunchedOnce"])
{
result=NO;
} else
{
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"hasLaunchedOnce"];
[[NSUserDefaults standardUserDefaults] synchronize];
result=YES;
}
flag=YES;
}
return result;
}
You can use a custom category method isFirstLaunch with UIViewController+FirstLaunch.
- (BOOL)isFirstLaunch
{
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"kFirstLaunch"]) {
return YES;
}
else {
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"kFirstLaunch"];
[[NSUserDefaults standardUserDefaults] synchronize];
return NO;
}
}
And when you need to use it in controller
BOOL launched = [self isFirstLaunch];
if (launched) {
//if launched
}
else {
//if not launched
}
Use NSUserDefaults. If the sharedDefault has a key for your app, its run before. Of course, you'll have to have the app create at least one default entry the first time the app runs.
Swift:
var isFirstLaunch: Bool {
get {
if (NSUserDefaults.standardUserDefaults().objectForKey("firstLaunchDate") == nil) {
NSUserDefaults.standardUserDefaults().setObject(NSDate(), forKey: "firstLaunchDate")
NSUserDefaults.standardUserDefaults().synchronize()
return true
}
return false
}
}
Another tip:
When using NSUserDefaults, these settings will be wiped if the app is ever deleted. If for some reason you require these settings to still hang around, you can store them in the Keychain.