Store userid in memory IOS - ios

I made an IOS Application with a login function. I use the ASIHTTPRequest for this to check if the user exists in a MySQL database. All works fine but i want to pass the userid trough other viewcontrollers or retrieve it on other parts of the app.
Can someone push me in the right direction how to do this in the best and most secure way?
This is my the way i do a POST HTTP request to a PHP script:
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:[NSURL URLWithString:#"*SOME_URL*"]];
In a callback i can retrieve the users ID, but i want to store this ID in the memory of the app for further use.
Thanks.

You can store userId in the AppDelegate.
Declare a userId property in AppDelegate.h with the following code:
#property (nonatomic, strong) NSString *userId
And then synthesize it in AppDelegate.m with the following code:
#synthesize userId;
You can then use userId from anywhere in your app. Add an import for the AppDelegate in the class you want to use userId, as follows:
#import "AppDelegate.h"
To retrieve the userId use the following code:
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSString *userId = [appDelegate userId];
And to set the userId use the following code:
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
[appDelegate setUserId:YouValueRetrievedByInternetOrWhateverYouWant];

Have a session class that works as a singleton and can be accessed with a static method.
To do this you can add a static method
+ (Session *)sharedInstace {
static Session *session;
if (!session)
session = [Session new]; // there are more proper ways to instantiate a singleton class, not gonna get into it now
return session.
}
On that class .h you should add a NSString (or a class of your choice or whatever you want) and you can access it from wherever with [Session sharedInstance].userID

Related

Objective-C: Keeping Variable Alive in Another Class

In my app, when the user launched the app, I create an instance of a class in my AppDelegate and call a method in the class which compares all of the user's iOS contacts to find which ones are using my app, and puts those contacts into an NSMutableArray
AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
...
GetContactClass *contact = [[GetContactClass alloc] init];
[contact getAllContacts];
...
}
GetContactClass.h
#property (retain, nonatomic) NSMutableArray *appContacts;
At the end of the getAllContacts method, I NSLog out appContacts and it works fine.
However, later in the app I try to set an NSMutableArray in a ViewController to equal appContacts, but I get a (null) array.
ViewController.m
self.searchableContacts = [[NSMutableArray alloc] init];
GetContactClass *contact = [[GetContactClass alloc] init];
self.searchableContacts = contact.appContacts;
What am I doing wrong here?
You're creating an entirely new instance which hasn't been asked to collect all contacts, so it hasn't stored them. By the look of the code the instance which has stored them has been destroyed. As you're running this on the main thread you might as well just ask the new instance to get contacts and delete the code for the old one. It's better however to run the contacts collection on a background thread and keep the result till you need it, in a retained instance variable.
If you want use this data in all app you must use a Pattern Design Singleton:
In objective-c:
#implementation Settings
+ (id)sharedInstance {
static Settings *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
Other way is change retain to strong but this is a bad idea and put this property in appDelegate and call all times APPDelegate get property.

Objective C - Global variables for every View Controller

I'm learning Objective C & Xcode, by doing my first App.
First a user has to sign in. And then he can do several things, like joining a group or changing his data (username, email,...).
The Login is finished and it works fine.
To the question:
Is it possible to set a variable which I can reach from every View Controller?
I tried it with the segues, but I think it's very hard to define this in every View Controller.
I'm searching for a global variable which I can reach from everywhere in the App, is this possible?
Or is there an other method to solve this?
Thank you for the help!
Emanuel
I would personally advise you to use the Singleton pattern.
I would not recommend putting everything into AppDelegate, this class is not meant for that.
Instead, what you can do is create a dedicated class (with a name like "ApplicationState", or whatever suits you), and put the properties you need in its header file, and having your singleton management code in the .m (and the prototype in the header)
If you need the singleton management code, here it is:
+ (ApplicationState*)sharedInstance
{
static ApplicationState* sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
Then, if you have in the header:
#property (nonatomic, strong) NSObject* object;
+ (ApplicationState*)sharedInstance;
You will be able to get this variable from anywhere by including the ApplicationState header file, and call:
[[ApplicationState sharedInstance] object];
You can use NSUserdefault if its simple .
Save:
[[NSUserDefaults standardUserDefaults]setObject:username forKey:#"userName"];
[[NSUserDefaults standardUserDefaults] synchronize];
NSLog(#"username saved = %#", username);
Read:
NSString *username = [[NSUserDefaults standardUserDefaults] objectForKey:#"userName"];
NSLog(#"username retrieved = %#", username);
You can use AppDelegate as well.
Define a property in your AppDelegate.h,
#property (nonatomic, strong) NSString *userName;
And then in your view controller, after importing AppDelegate.h,
AppDelegate *appDel = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSLog(#"%#", appDel.userName);
You can put them in plist or you can create Objective-C class initialize your variables within and import header in .pch file, then this class with data will available in every ViewController

Setter in NSString iOS

hi i am new to ios dev ,I am trying to set a value for nsstring from delegate class and access from other class ,the value i get is null.i dont know what mistake i am doing?
//token class header file
#interface TokenClass : NSObject
{
NSString *tokenValue;
}
#property (nonatomic,strong) NSString *tokenValue;
//token class main file
#implementation TokenClass
#synthesize tokenValue;
#end
//App Delegate
TokenClass *token = [[TokenClass alloc]init];
[token setTokenValue:#"as"];
when i access tokenvalue in some other classs i get null value.
can any one point me what mistake i am doing?Am i using # property correctly?
There are a lot of ways to achieve what you want:
1. Usually I am using NSUserDefaults to save small amount of data which I will need even the user closed the app. There are a lot of information how to use it. See my answer here.
2. In your UIViewController class (e.x. your rootViewController) create #property which will hold your TokenClass. Then you will get tokenValue by self.tokenClass.tokenValue
3. The other way is create a singleton class which will be available during the whole run loop of your application. A Singleton candidate must satisfy three requirements:
controls concurrent access to a shared resource.
access to the resource will be requested from multiple, disparate
parts of the system.
there can be only one object.
+(TokenClass*) sharedTokenClass {
static dispatch_once_t pred;
static TokenClass *_sharedTokenClass = nil;
dispatch_once(&pred, ^{
_sharedTokenClass = [[TokenClass alloc] init];
});
return _sharedTokenClass;
}
You will use it it from any place you want by
[TokenClass sharedTokenClass]tokenValue];
If I were you, I would use the first variant.
PS. I strongly recommend you to read some memory management articles to get the point of object's lifecycle.
You need to use Singleton class to expose variables or objects to the entire project or create global variables. Create sharedInstance of TokenClass class and create property which can be accessed anywhere
in your .h file
//token class header file
#interface TokenClass : NSObject
#property (nonatomic,strong) NSString *tokenValue;
//create static method
+ (id)sharedInstance;
in .m file
#import "TokenClass.h"
#implementation TokenClass
#pragma mark Singleton Methods
+ (id)sharedInstance {
static TokenClass *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
- (id)init {
if (self = [super init]) {
tokenValue = [[NSString alloc] init];
}
return self;
}
#end
now in your appDelegate
#import TokenClass.h
#implementation AppDelegate
in `didFinishLaunchingWithOptions:`
[TokenClass sharedInstance] setTokenValue:#"as"];
in any class you can get value using
NSLog(#"tokenValue = %#", [[SingletonClass sharedInstance] tokenValue]);

iOS Twitter Reverse OAuth

I have been pouring over the internet for days now trying to figure out how to implement this.
I need to request the access token and secret from twitter in order to pass this to a server that will process the users tweets for my application.
I have been following this link https://dev.twitter.com/docs/ios/using-reverse-auth
The problem is step 1. They dont give you an example of step 1.
Here is my code:
NSURL *url = [NSURL URLWithString:TW_OAUTH_URL_REQUEST_TOKEN];
NSDictionary *parameters = #{TW_X_AUTH_MODE_KEY:TW_X_AUTH_MODE_REVERSE_AUTH};
SLRequest *getTwitterAuth = [SLRequest requestForServiceType:SLServiceTypeTwitter requestMethod:SLRequestMethodGET URL:url parameters:parameters];
// Assume that we stored the result of Step 1 into a var 'resultOfStep1'
NSString *S = resultOfStep1;
NSDictionary *step2Params = [[NSMutableDictionary alloc] init];
[step2Params setValue:#"kfLxMJsk7fqIuy8URhleFg" forKey:#"x_reverse_auth_target"];
[step2Params setValue:S forKey:#"x_reverse_auth_parameters"];
NSURL *url2 = [NSURL URLWithString:#"https://api.twitter.com/oauth/access_token"];
SLRequest *stepTwoRequest =
[SLRequest requestForServiceType:SLServiceTypeTwitter requestMethod:SLRequestMethodPOST URL:url2 parameters:step2Params];
// You *MUST* keep the ACAccountStore alive for as long as you need an ACAccount instance
// See WWDC 2011 Session 124 for more info.
self.accountStore = [[ACAccountStore alloc] init];
// We only want to receive Twitter accounts
ACAccountType *twitterType =
[self.accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
// Obtain the user's permission to access the store
[self.accountStore requestAccessToAccountsWithType:twitterType
withCompletionHandler:^(BOOL granted, NSError *error) {
if (!granted) {
// handle this scenario gracefully
} else {
// obtain all the local account instances
NSArray *accounts =
[self.accountStore accountsWithAccountType:twitterType];
// for simplicity, we will choose the first account returned - in your app,
// you should ensure that the user chooses the correct Twitter account
// to use with your application. DO NOT FORGET THIS STEP.
[stepTwoRequest setAccount:[accounts objectAtIndex:0]];
// execute the request
[stepTwoRequest performRequestWithHandler:
^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
NSString *responseStr =
[[NSString alloc] initWithData:responseData
encoding:NSUTF8StringEncoding];
// see below for an example response
NSLog(#"The user's info for your server:\n%#", responseStr);
}];
}
}];
I have been trying to figure out how I process the SLRequest in oder to pass it to step 2 from the twitter docs.
I have also used this here: https://github.com/seancook/TWReverseAuthExample
This code is great but very complex. Any help would be greatly appreciated! Thanks!
The reason step one doesn't have any code is that they assume you will do this on your server or before hand or something like that. Basically you need to generate a key that your app will use to convert iOS tokens to normal tokens.
There is a script that will make the request for you here: http://www.ananseproductions.com/twitter-reverse-auth-headaches/ Its written in ruby so you could use something similar if you have a ruby server.
Personally I would have my app request this token from my server, then make the request to twitter, then post the new token back to my server.
Here is a class to help accomplish just this with a single method call that returns a dictionary with the token and token secret.
https://github.com/kbegeman/Twitter-Reverse-Auth
Hope this helps others out!
As of this code https://github.com/seancook/TWReverseAuthExample , it's fairly simple to implement in your own application. I prefer to create reusable classes, so I don't have to implement the same code multiple times. Normally you would create some singleton and work with it on the following tutorial. However the point of this instruction is not to teach you how to create singletons, so for the simplicity sake, we will use AppDelegate.h/m which is easily accessible from all over the application.
All you have to do is the following:
Open yours and Sean Cook's project (the one which URL is above)
Drag and copy Source->Vendor->ABOauthCore group into your project
Select TWAPIManager.h/m, TWSignedRequest.h/m and copy them into your project
Add the below code into your AppDelegate.h file
#property (nonatomic, strong) ACAccountStore* store;
#property (nonatomic, strong) TWAPIManager *apiManager;
#property (nonatomic, strong) NSArray *accounts;
-(void)storeAccountWithAccessToken:(NSString *)token secret:(NSString *)secret;
-(void)performReverseAuth:(id)sender inView:(UIView*)viewToDisplaySheet;
-(void)_refreshTwitterAccounts;
Now paste the following methods into your AppDelegate.m file
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex;
-(void)_refreshTwitterAccounts;
-(void)_obtainAccessToAccountsWithBlock:(void (^)(BOOL))block;
-(void)performReverseAuth:(id)sender inView:(UIView*)viewToDisplaySheet;
In some initialization method of your file, or as of this example in: `application: didFinishLaunchingWithOptions' paste the following code:
_store = [[ACAccountStore alloc] init];
_apiManager = [[TWAPIManager alloc] init];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(_refreshTwitterAccounts) name:ACAccountStoreDidChangeNotification object:nil];
Remember to remove observer using the following code. Paste it in AppDelegate.m:
-(void)dealloc{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
Open your app-Info.plist file and add 2 string keys. Take their values from: https://apps.twitter.com/
TWITTER_CONSUMER_KEY
TWITTER_CONSUMER_SECRET
In the View Controller that you want to use to implement twitter features, in the viewDidLoad method, add the following code:
AppDelegate* appDelegate = [UIApplication sharedApplication].delegate;
[appDelegate _refreshTwitterAccounts];
OK, finally you are ready to start the whole machine. In the View Controller that you want to use to implement twitter features, create UIButton called _reverseAuthBtn and create an IBAction to it. Then in your IBAction paste the following code:
AppDelegate* appDelegate = [UIApplication sharedApplication].delegate;
[appDelegate performReverseAuth:sender inView:self.view];
Whew, I guess that's it! If I haven't forgotten about anything, you have got Twitter Reverse Oauth implementation, and if you want to use it in multiple view controllers, all you have to do is do steps 1-8, and then paste the code from the steps 9 and 10 into your view controller.
Best regards!
Use this lib, it works perfectly!
https://github.com/nst/STTwitter
Info how to implement: https://github.com/nst/STTwitter#reverse-authentication
:)

Access to core data database in other class

i have a core data database that start from the AppDelegate, and there i'll do this:
MasterViewController *masterViewController = [[[MasterViewController alloc] initWithNibName:#"MasterViewController" bundle:nil] autorelease];
masterViewController.managedObjectContext = self.managedObjectContext;
so in this way i can access to the database in the master view, then i want access to the core data in other classes, and i do this:
id delegateContext = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [delegateContext managedObjectContext];
but when i add, and access the information, i have some bad Exc access and other error in various part of the code when i try to access to the information of the database, so i think that maybe i have used in bad way the core data, to access the information from other classes.
maybe i have to release the delegatecontext?...i haven't release it in any class i have used it, and if i have release it, where i have do it?
anyone can help me?
Problem is you are taking delegateContext of type id instead of NSManagedObjectContext and assigning it to *contextin these two lines.
id delegateContext = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [delegateContext managedObjectContext];
How about adding these lines whenever you need to save or access managedObjectContext, check it if its nil if YES copy it from Appdelegate.
if (managedObjectContext == nil)
{
managedObjectContext = [(AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
NSLog(#"After managedObjectContext: %#", managedObjectContext);
}
Just try to remove your these two lines and add the above if condition I am suggesting. Should work.
Update 1: As you are asking I am mentioning steps for creating
Appdelegate's instance to access global properties.
#import "AppDelegate.h"
after #implementation create instance of Appdelegate
AppDelegate *app;
in viewDidLoad method...
app=(AppDelegate *)[[UIApplication sharedApplication]delegate];

Resources