I'm developing an app in Objective C and everything is cool but i am really new in this, so i was wondering if there is a way to save the session from a user that has already logged in into my app, I save the username + password cause I use them later but when i close the app, (kill it), i have to log in again, so i was hoping that you guys could help me with this:
Here is how i save the session in my code:
NSString *user = [textUser text];
NSString *password = [textPassword text];
[[NSUserDefaults standardUserDefaults] setObject:user forKey:#"userName"];
[[NSUserDefaults standardUserDefaults] setObject:password forKey:#"userPassword"];
[[NSUserDefaults standardUserDefaults] synchronize];//here is where i save the user info but i want it to stay even if the app is killed
So what i think i need is a method that checks if NSUserDefaults is empty or not, then go straight to my home-screen-activity
Thanks!
I'm not sure, whether I understood your Q correctly!? Do you want to know how to check, whether there are already log-in data?
NSString *user = [[NSUserDefaults standardUserDefaults] objectForKey:#"userName"];
if (user)
{
// User name already has been stored
…
}
else
{
// User name is not stored
}
Use this Method to check login:
method returns YES if user already logged in else returns NO.
-(BOOL)CheckLogin{
if ([[NSUserDefaults standardUserDefaults]valueForKey:#"userName"] && [[NSUserDefaults standardUserDefaults]valueForKey:#"userPassword"]) {
//go straight to my home-screen-activity
return YES;
}
else{
//required to login
return NO;
}
}
Hope this helps.
Related
I'm using the CocoaLibSpotify library to develop an iOS application that will utilize the Spotify API. I've got it just about where I want it, but I've run into a bit of a problem.
When the user touches my "Logout of Spotify" button, I execute the following code:
-(IBAction)logoutButtonTouched:(id)sender
{
// Clear out the user's settings that I am saving.
NSString *appDomain = [[NSBundle mainBundle] bundleIdentifier];
[[NSUserDefaults standardUserDefaults] removePersistentDomainForName:appDomain];
[[SPSession sharedSession] logout:^(void) {
SPLoginViewController *controller = [SPLoginViewController loginControllerForSession:[SPSession sharedSession]];
controller.allowsCancel = NO;
}];
}
This does indeed logout the user and display the SPLoginViewController, but my problem is, the username and password field still contain the values that they'd logged-in with. Does anyone know of a way to clear these fields when I display the SPLoginViewController?
This functionality isn't in the login controller, which is indeed a bug.
You can do it like this. Please note that this is really fragile code and will fail if any internal detail of the login controller changes, and it will in the future:
SPLoginViewController *controller = [SPLoginViewController loginControllerForSession:[SPSession sharedSession]];
id internalLoginViewController = [controller.viewControllers objectAtIndex:0];
UITextField *loginField = [internalLoginViewController valueForKey:#"usernameField"];
UITextField *passwordField = [internalLoginViewController valueForKey:#"passwordField"];
loginField.text = #"";
passwordField.text = #"";
I've been banging my head against the wall for several days trying to understand how to perform an action as soon as the application starts.
Basically I want to download a plist from my website if the user turns on a switch that determines if he wants to download new contents at startup.
Point is that:
"A" class has the method to reload the contents;
"B" class has the switch that, if turned on, tells the delegate to perform the reload contents method as soon as the application starts
Now, I don't know how to tell the AppDelegate to run the method of class "A" if the switch of class "B" is turned on. Obviously I need to use NSUserDefaults, but i'm pretty lost after that.
Can anyone make things clearer? Or, is there a more comfortable workaround to do it?
yes you can do this using NSUserDefaults
in your class b.
-(void)swithChanged
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
//check if !null
if(![[defaults objectForKey:#"shouldDownload"]isKindOfClass:[NSNull class]]){
if([(NSNumber*)[defaults objectForKey:#"shouldDownload"]boolValue])
{
[defaults setObject:[NSNumber numberWithInt:0] forKey:#"shouldDownload"];
[defaults synchronize];
}else{
[defaults setObject:[NSNumber numberWithInt:1] forKey:#"shouldDownload"];
[defaults synchronize];
}
}else{
//set your NSUserDefault here for the first time
}
}
in your AppDelegate
- (void)applicationDidBecomeActive:(UIApplication *)application{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
//check if !null
if(![[defaults objectForKey:#"shouldDownload"]isKindOfClass:[NSNull class]]){
if([(NSNumber*)[defaults objectForKey:#"shouldDownload"]boolValue])
{
//you can write the downloadData method in this appDelegate,
//[self downloadData]
//OR
AClass *aClass = [AClass alloc]init];
[aClass downloadData];
}else{
//do not download
}
}else{
//the default behaviour of app, download or not?
}
}
Here's a post that could help you understand the flows during application start-up:
http://www.cocoanetics.com/2010/07/understanding-ios-4-backgrounding-and-delegate-messaging
Also, check this post:
applicationWillEnterForeground vs. applicationDidBecomeActive, applicationWillResignActive vs. applicationDidEnterBackground
How would I check if it is the first launch of of my application using NSUserDefaults and running some code for the first time my app opens?
This should point you in the right direction:
static NSString* const hasRunAppOnceKey = #"hasRunAppOnceKey";
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
if ([defaults boolForKey:hasRunAppOnceKey] == NO)
{
// Some code you want to run on first use...
[defaults setBool:YES forKey:hasRunAppOnceKey];
}
The NSUserDefaults answer is the first thing that popped in my head, but upon reflection I will make another suggestion. A bit more work, but it's worth considering. The motive is: sometimes when troubleshooting an app, Apple recommends deleting that app's plist file. It's a fairly ubiquitous troubleshooting technique. I would recommend storing your boolean in your plist file instead of NSUserDefaults.
Disclaimer: I only do iOS development, so I'm not sure how NSUserDefaults and plists interact on the Mac, and I don't know what all is involved in getting your plist to live in ~/Library/Application\ Support/Preferences/com.mycompany.MyAppName.plist
Anyway, I imagine what this requires is having some code which can actually author a "fresh" plist (probably a copy from a template file in your bundle), and you app does this if it launches and does not see a plist. The default plist should not include the flag which lets your users skip the 'first time' code, but if they have opened the app before, and then delete the plist, they should get default behavior back.
This is an important behavior to support where possible, to aide our users if our app ever gives them trouble.
if (![[NSUserDefaults standardUserDefaults] boolForKey:#"hasBeenLaunched"]) {
// Run code on the first launch only ...
[defaults setBool:YES forKey:#"hasBeenLaunched"];
}
You can use NSUserDefaults to save bools, integers, objects into the program and have them available whenever you open it. You can use 'boolForKey' to set a flag called "hasBeenLaunched". By default, this value will be NO when not set. Once you change it to YES, the code in the if condition will never be executed again.
In your main controller class, implement something like this:
static NSString * const MDFirstRunKey = #"MDFirstRun";
#implementation MDAppController
+ (void)initialize {
NSMutableDictionary *defaults = [NSMutableDictionary dictionary];
[defaults setObject:[NSNumber numberWithBool:YES] forKey:MDFirstRunKey];
[[NSUserDefaults standardUserDefaults] registerDefaults:defaults];
// the following if on Mac and is necessary:
[[NSUserDefaultsController sharedUserDefaultsController] setInitialValues:defaults];
}
- (void)applicationDidFinishLaunching:(NSNotification *)notification {
BOOL firstRun = [[[NSUserDefaults standardUserDefaults]
objectForKey:MDFirstRunKey] boolValue];
if (firstRun) {
// do something
[[NSUserDefaults standardUserDefaults] setObject:
[NSNumber numberWithBool:NO] forKey:MDFirstRunKey];
} else {
// do something else
}
}
#end
The +initialize class method is called before an instance of the class it's found in is created; in other words, it is called very early on, and is a good place to set up your default values.
See Preferences and Settings Programming Guide: Registering Your App's Default Preferences for more info.
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];
}
I am developing a cocoa application. I created a user default object with this code:
NSUserDefaults *standard_user_defaults = [NSUserDefaults standardUserDefaults];
if (standard_user_defaults) {
[standard_user_defaults setObject:myString forKey:key];
[standard_user_defaults synchronize];
}
And then, I am getting the value with this code:
NSUserDefaults *standard_user_defaults = [NSUserDefaults standardUserDefaults];
NSString *val = nil;
if (standard_user_defaults)
val = [standard_user_defaults objectForKey:key];
The problem is that if I run this application in my computer is working fine, and I can get the user default value, but if another person runs the application is getting an empty value. Any ideas?
I assume by “another person” you mean another user on your computer. The reason they cannot read what you’ve written to your user defaults is because NSUserDefaults is meant for user-specific values. To save something that your application will be able to access from both your user account and others’, you need to place it in a file stored somewhere in a shared location on the system. One way to do this would be something like this:
NSString *basePath = [NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSLocalDomainMask, YES) objectAtIndex:0];
NSString *filePath = [basePath stringByAppendingPathComponent:#"someFileName"];
// write:
NSDictionary *dataToSave = [NSDictionary dictionaryWithObjectsAndKeys:theValue, #"someKey", nil];
if(filePath && [dataToSave writeToFile:filePath atomically:YES])
{
// success!
}
// read:
NSDictionary *dataToLoad = [NSDictionary dictionaryWithContentsOfFile:filePath];
if(dataToLoad)
{
// success!
NSString *theValue = [dataToLoad objectForKey:#"someKey"];
}
You should try and use valueForKey rather than objectForKey. Looking at your code, there is no reason it shouldn't work for one person and not another.
The one exception would be if you are using the defaults from the settings.bundle. Values stored into settings.bundle for user defaults are not initialized until the user opens the settings page for the first time.