Passing data just isn't doing the trick...I need to pull string data from a view controller when a function in the AppDelegate is called. Here's the code:
In App Delegate:
- (void)applicationDidEnterBackground:(UIApplication *)application
{
AMViewController *viewController = [[AMViewController alloc] initWithNibName:#"AMViewController" bundle:nil];
self.xpData = viewController.xpLabel.text;
NSLog(#"Value of xpString in AD: %#", self.xpData);
}
In my ViewController, I'm not using an action to pass/retrieve the string. I'm basically pulling it from the ViewController when the user hits the home button. I'm doing this because I'd like to save my data on exit. Thanks!
In your AppDelegate.h
#property (atomic, copy) NSString *yourString;
Where you have changed xpLabel.text, do this
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
appDelegate.yourString = xpLabel.text;
Now in
- (void)applicationDidEnterBackground:(UIApplication *)application
{
NSLog(#"Value of xpString in AD: %#", self.yourString);
}
Another Method
Set your value in AMViewController class like this
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
[prefs setObject:xpLabel.text forKey:#"yourkey"];
[prefs synchronize];
Get your Value in applicationDidEnterBackground like this
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
yourString = [prefs stringForKey:#"yourkey"];
Did you tried working with NSNotificationCenter
Or shared delegate:
http://www.roostersoftstudios.com/2011/04/12/simple-delegate-tutorial-for-ios-development/
http://coderchrismills.wordpress.com/2011/05/05/basic-delegate-example/
Related
There should be a registration page with Full Name, User Name, Password, Email and Register Button.
When we Click on Register Button we then go to Login Page where it validate the username and password that we created in registration page using NSUserDefaults.
Now if we give right credentials then it should redirect to logout page and when we next time open the app it should directly redirect to logout page.
Data Should be stored locally using NSUserDefaults(value should be stored in string format).
Login view controller .h
#import <UIKit/UIKit.h>
#interface ViewController2 : UIViewController
#property(strong, nonatomic)NSString *dataString;
#property(strong, nonatomic)NSString *dataString2;
#property (strong, nonatomic) IBOutlet UILabel *lblOutput;
#property (strong, nonatomic) IBOutlet UITextField *inputTxt1;
#property (strong, nonatomic) IBOutlet UITextField *inputTxt2;
- (IBAction)btnAction:(id)sender;
#end
Login view controller .m
#import "ViewController2.h"
#interface ViewController2 ()
#end
#implementation ViewController2
- (void)viewDidLoad {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *firstName = [defaults objectForKey:#"firstName"];
NSString *lastName = [defaults objectForKey:#"lastname"];
firstName = _inputTxt1.text;
lastName = _inputTxt2.text;
[super viewDidLoad];
NSLog(#"%#",self.dataString);
NSLog(#"%#",self.dataString2);
self.navigationItem.title = #"Login Page";
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)btnAction:(id)sender {
NSString *firstName = [_inputTxt1 text];
NSString *lastName = [_inputTxt2 text];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:firstName forKey:#"firstName"];
[defaults setObject:lastName forKey:#"lastname"];
[defaults synchronize];
// [Defaults setObject:#"Eezy"forKey:#"iOS"];
NSLog(#"%#",[defaults stringForKey:#"firstName"]);
NSLog(#"%#",[defaults stringForKey:#"lastName"]);
if ([self.dataString isEqualToString:[defaults objectForKey:#"firstName"]] && [self.dataString2 isEqualToString:[defaults objectForKey:#"lastName"]])
{
NSLog(#"goog");
[self performSegueWithIdentifier:#"segueToNextPage2" sender:self];
}
else
{
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"Hey Listen" message:#"Wrong User Name or Password" delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil, nil];
[alert show];
}
}
#end
The problem is that I have passed the value from registration page but when I am storing it in NSUserDefault then it is storing the value of username but in case of password it is showing null value.
FOR Saving login values you can use
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
// saving an NSString
[prefs setObject:txtUsername.text forKey:#"userName"];
[prefs setObject:txtPassword.text forKey:#"password"];
[prefs synchronize];
FOR RETRIEVING Values
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
// getting an NSString
NSString *savedUsername = [prefs stringForKey:#"userName"];
NSString *savedPassword = [prefs stringForKey:#"password"];
For logout:
[[NSUserDefaults standardUserDefaults] removeObjectForKey:#"Your Key"];
Here is the Solution i got :-
Step 1: In login page define a bool variable and set its value as true on clicking the login button
- (IBAction)btnAction:(id)sender {
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
[prefs setBool:YES forKey:#"registered"];
[prefs synchronize];
}
Step 2. Create a storyBoard in identity inspector as "UITabBarController". Keep in mind this will be the page where you want to go.
Step 3. In AppDelegate.h file just below #implemention write following code :-
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"registered"]) {
UITabBarController *controller = [self.window.rootViewController.storyboard instantiateViewControllerWithIdentifier:#"UITabBarController"];
self.window.rootViewController = controller;
}
return YES;
}
That's it very simple.
Save the details in NSUserDefaults from registration page. Also make entry in NSUserDefaults to check whether user logged in or not.
[[NSUserDefaults standardUserDefaults]setValue:#"YES" forKey:#"isLoggedIn"];
In your AppDelegate's didFinishLaunching method, change the initialViewController based on isLoggedIn key value e.g.
if ([[[NSUserDefaults standardUserDefaults]valueForKey:#"isLoggedIn"] isEqualToString:#"YES"])
{
// redirect to logout screen
}
else
{
//show login or register screen
}
I have a ViewcontrollerA as a form filling page and to perform a calculation I push a new viewcontrollerB now when I pop to ViewcontrollerA the existing contents are cleared
My code is
In viewcontroller A
JS_skill *skill_VC = [[JS_skill alloc] initWithNibName:#"JS_skill" bundle:nil];
[[self navigationController] pushViewController:skill_VC animated:NO];
In viewcontroller B
[self.navigationController popViewControllerAnimated:YES];
A quick option would be to save the values of the textfields in userDefaults before you push the viewcontroller. Then when you return to the viewController in viewWillAppear set the textfields back to what you have in userDefaults:
//Just before you push the viewController:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setValue:#"Example Name" forKey:#"nameTextField"];
[defaults setValue:#"Example Surname" forKey:#"surnnameTextField"];
//In ViewWillAppear:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
textField.text = [defaults valueForKey:#"nameTextField"];
surnameField.text = [defaults valueForKey:#"surnnameTextField"];
I don't seem to be able to mock NSUserDefaults. I want it to send back the data that I tell it too but instead, it sends back the data stored in it from when running the app.
I am using:
Specta
Expecta
OCMockito
I have the following test:
describe(#"AppDelegate", ^{
__block AppDelegate *appDelegate;
beforeEach(^{
appDelegate = [AppDelegate new];
});
afterEach(^{
appDelegate = nil;
});
describe(#"application did finish launching with options", ^{
beforeEach(^{
[appDelegate application:nil didFinishLaunchingWithOptions:nil];
NSUserDefaults *mockUserDefaults = mock([NSUserDefaults class]);
[given([mockUserDefaults objectForKey:#"currentUser"]) willReturn:nil];
});
it(#"should have a login view controller as root view controller", ^{
expect(appDelegate.window.rootViewController).to.beKindOf([ToALoginViewController class]);
});
});
});
So the above test fails because it actually returns some data for currentUser. What am I doing wrong?
Following on from what Ken Kuan said, I made the following changes:
AppDelegate.h
#property (strong, nonatomic) NSUserDefaults *userDefaults;
- (void)setUserDefaults:(NSUserDefaults *)userDefaults;
AppDelegate.m
- (void)setUserDefaults:(NSUserDefaults *)userDefaults {
_userDefaults = userDefaults;
}
AppDelegateSpec.m
beforeEach(^{
[appDelegate application:nil didFinishLaunchingWithOptions:nil];
NSUserDefaults *mockUserDefaults = mock([NSUserDefaults class]);
[appDelegate setUserDefaults:mockUserDefaults];
[given([mockUserDefaults objectForKey:#"currentUser"]) willReturn:nil];
});
However, I still get the same problem.
You can mock NSUserDefaults. I have this code which is working fine.
When you are mocking NSUserdefaults make sure you are stopping mock at the end of test case, otherwise it would cause errors in other places where you are using NSUserDefaults.
id userDefaultsMock = OCMClassMock([NSUserDefaults class]);
OCMStub([userDefaultsMock standardUserDefaults]).andReturn(userDefaultsMock);
OCMStub([[userDefaultsMock standardUserDefaults] boolForKey:SHOWMYNAME]).andReturn(#"N");
[self.myObject codewithuserdefaults];
OCMVerify( [[NSUserDefaults standardUserDefaults] setValue:[OCMArg any] forKey:FIRSTNAME]);
[userDefaultsMock stopMocking];
You must use [NSUserDefaults standardUserDefaults] in appDelegate which is actual user defaults, not your mock.
A solution is to make user default to a property of app delegate and set it with your mockUserDefaults in tests.
Another one is to swizzle [NSUserDefaults standardUserDefaults] to return your mockUserDefaults in your tests.
So with much thanks to Ken Kuan, I managed to solve the problem I was having. Heres how I achieved it.
I added a NSUserDefaults property to the AppDelegate and a setter function.
I set self.userDefaults to [NSUserDefaults standardUserDefaults] in application:willFinishLaunchingWithOptions:.
I then set the rootViewController in application:didFinishLaunchingWithOptions:
AppDelegate.h
#property (strong, nonatomic) NSUserDefaults *userDefaults;
- (void)setUserDefaults:(NSUserDefaults *)userDefaults;
AppDelegate.m
- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.userDefaults = [NSUserDefaults standardUserDefaults];
return YES;
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
NSData *encodedUserData = [self.userDefaults objectForKey:#"currentUser"];
if (encodedUserData) {
NSLog(#"Have current user");
self.window.rootViewController = [ThermostatViewController new];
} else {
NSLog(#"No current user");
self.window.rootViewController = [ToALoginViewController new];
}
[self.window makeKeyAndVisible];
return YES;
}
- (void)setUserDefaults:(NSUserDefaults *)userDefaults {
_userDefaults = userDefaults;
}
AppDelegateSpec.m
describe(#"application will finish launching with options", ^{
beforeEach(^{
[appDelegate application:nil willFinishLaunchingWithOptions:nil];
});
context(#"application did finish launching with options and with no current user", ^{
beforeEach(^{
NSUserDefaults *mockUserDefaults = mock([NSUserDefaults class]);
[appDelegate setUserDefaults:mockUserDefaults];
[given([mockUserDefaults objectForKey:#"currentUser"]) willReturn:nil];
[appDelegate application:nil didFinishLaunchingWithOptions:nil];
});
it(#"should have a login view controller as root view controller", ^{
expect(appDelegate.window.rootViewController).to.beKindOf([ToALoginViewController class]);
});
});
});
i have been looking at tutorials for weeks now, not been able to find ANY storyboard examples implementing FB in iOS.
i got my app to open the FBloginscreen, request user auth for app, and then return to app...
like some other users , fbdidlogin and handleopenurl method are not called. i am sure i am doing something wrong but just don't know what.
i am using the default view controller in my storyboard (i did not create a vc programatically
) so i might need to do something with that.
from what i understand that handleopenurl method needs to be in my app delegate.m file and not in my view controller.m file, but i am not sure how it should be written and how to connect a UIViewController object i create to the VC in my storyboard (the one with the buttons and labels that i am using).
ViewController.h (relevant to FB)
#import "FBConnect.h"
#interface ViewController : UIViewController
<UIImagePickerControllerDelegate,
UINavigationControllerDelegate, FBSessionDelegate, FBDialogDelegate>
{
Facebook *facebook;
}
#property (nonatomic,retain) Facebook *facebook;'
ViewController.m (relevant to FB)
#import "ViewController.h"
#implementation ViewController;
#synthesize facebook;
-(void)LogintoFB
{
facebook = [[Facebook alloc] initWithAppId:#"345872345487883" andDelegate:self];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:#"FBAccessTokenKey"]
&& [defaults objectForKey:#"FBExpirationDateKey"]) {
facebook.accessToken = [defaults objectForKey:#"FBAccessTokenKey"];
facebook.expirationDate = [defaults objectForKey:#"FBExpirationDateKey"];
}
if (![facebook isSessionValid]) {
[facebook authorize:nil];
NSLog(#"did log in");
}
}
// Pre iOS 4.2 support
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
NSLog(#"-4.2 got calleld");
return [facebook handleOpenURL:url];
}
// For iOS 4.2+ support
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
NSLog(#"4.2+ got called");
return [facebook handleOpenURL:url];
}
}
- (void)fbDidLogin {
NSLog(#"fbDidLogin");
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:[facebook accessToken] forKey:#"FBAccessTokenKey"];
[defaults setObject:[facebook expirationDate] forKey:#"FBExpirationDateKey"];
[defaults synchronize];
[facebook dialog:#"feed" andDelegate:self];
}'
also if you can direct me to a tutorial that used storyboard when implementing Facebook in iOS that would be great.
thank you!
-(BOOL)application:openURL:sourceApplication:annotation: should be implemented in the app delegate.
Add a property to the appDelegate :
#property (nonatomic, strong) Facebook *facebook;
Synthesize it!
In your logintoFB method add this after creating the Facebook object
(AppDelegate should be whatever your appDelegate class name is)
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
appDelegate.facebook = facebook;
I am trying to integrate Facebook to my iOS app with ARC. To use FB SDK, I have disabled ARC with "-fno-objc-arc" for those files. However, it still have EXC_BAD_ACCESS error and I need to change
#property(nonatomic, assign) id<FBSessionDelegate> sessionDelegate;
to
#property(nonatomic, retain) id<FBSessionDelegate> sessionDelegate;
The login is working now but the UITextView is not updated after login
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:#"FBAccessTokenKey"]
&& [defaults objectForKey:#"FBExpirationDateKey"]) {
[delegate facebook].accessToken = [defaults objectForKey:#"FBAccessTokenKey"];
[delegate facebook].expirationDate = [defaults objectForKey:#"FBExpirationDateKey"];
[defaults synchronize];
}
if (![[delegate facebook] isSessionValid])
{
[[delegate facebook] authorize:nil];
}
}
- (void)fbDidLogin
{
AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:[[delegate facebook] accessToken] forKey:#"FBAccessTokenKey"];
[defaults setObject:[[delegate facebook] expirationDate] forKey:#"FBExpirationDateKey"];
[defaults synchronize];
[[delegate facebook] requestWithGraphPath:#"me" andDelegate:self];
}
- (void)request:(FBRequest *)request didLoad:(id)result
{
if ([result isKindOfClass:[NSArray class]]) {
result = [result objectAtIndex:0];
}
if ([result objectForKey:#"name"]) {
self.uitextview.text = [result objectForKey:#"name"];
}
}
I have checked that "[result objectForKey:#"name"]" will return a result but "self.uitextview" is not recognized.
How do I update a UITextView after successful login?
Found out that the ViewController init in Appdelegate can't be used as shown in Facebook Hackbook sample.
Replace with the following declaration:
UITabBarController *tabBarController = (UITabBarController *) self.window.rootViewController;
ViewController *viewcontroller = [[tabBarController viewControllers] objectAtIndex:4];
http://www.raywenderlich.com/5138/beginning-storyboards-in-ios-5-part-1