I tried too much to solve my bellow issue but i am failed.Please help me to solve this issue. I have login view and after validating id and password i am pushing it to next view controller.Please check bellow image.
Issue - When Id and Password is correct it's pushing to next view controller but after 2 clicks on login button.
Code -
ServiceManager.m
-(void)initGetAppServiceRequestWithUrl:(NSString *)baseUrl onCompletion:
(ServiceCompletionHandler)handler
{
NSString *fullUrl = [NSString stringWithFormat:#"%#",[baseUrl
stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL
URLWithString:fullUrl]];
[NSURLConnection sendAsynchronousRequest:(NSURLRequest *)request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response,NSData *data,NSError *error)
{
if (error) {
handler(nil,error);
// NSLog(#"error = %#",error);
}
else
{ handler(data, nil);
// NSLog(#"data = %#",data);
}
}];
}
JSONResponseHandler.m
+(void)handleResponseData:(NSData *)responseData onCompletion:(JSONHandler)handler
{
if (responseData) {
NSError *jsonParseError;
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:responseData
options:kNilOptions error:&jsonParseError];
if (!json) {
handler(nil , jsonParseError);
}
else
{
handler (json , nil);
}
}
}
ASKevrServiceManager.m
-(void)login:(Login *)login completionHandler:(ServiceCompletionHandler)handler
{
NSString *loginUrl = [NSString
stringWithFormat:#"http://249development.us/johnsan/askever/login.php?
login=%#&password=%#",login.emailAddr , login.password];
[self initGetAppServiceRequestWithUrl:loginUrl onCompletion:^(id object, NSError
*error)
{
handler(object , error);
}
];
}
ASKevrOperationManager.m
+(void)login:(Login *)login handler:(OperationHandler)handler
{
ASKevrServiceManager *serviceManager = [[ASKevrServiceManager alloc]init];
[serviceManager login:login completionHandler:^(id object, NSError *error)
{
[JSONResponseHandler handleResponseData:object onCompletion:^(NSDictionary
*json , NSError *jsonError)
{
if(json)
{
handler(json , nil , YES);
}
else
{
handler(nil , jsonError , NO);
}
}];
}];
}
LoginViewController.m
-(BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender
{
if ([identifier isEqualToString:#"pushTab"])
{
if ([emailTxt.text isEqualToString:#""] || [passwordTxt.text
isEqualToString:#""])
{
[self showAlertWithMessage:#"Please write your id or password"];
return NO;
}
else
{
Login *loginModel = [[Login alloc]init];
loginModel.emailAddr =emailTxt.text;
loginModel.password = passwordTxt.text;
[ASKevrOperationManager login:loginModel handler:^(id object , NSError *error ,
BOOL success)
{
if (success)
{
NSLog(#"object =%#",object);
NSDictionary *arr = [object objectForKey:#"response"];
str = [arr objectForKey:#"flag"];
//check for error
NSDictionary *toDict = [object objectForKey:#"response"];
currentUserId = [toDict objectForKey:#"c_id"];
NSLog(#"currentUserId = %#",currentUserId);
}
else
{
[self showAlertWithMessage:#"Wrong Id or Password."];
}
}];
NSLog(#"str = %#",str);
if ([str isEqualToString:#"1"])
{
// [self showAlertWithMessage:#"Wrong Id or Password."];
return YES;
}
}
}
return NO;
}
When pressing login button do run the code
if (![emailTxt.text isEqualToString:#""] &&
![passwordTxt.text isEqualToString:#""]){
Login *loginModel = [[Login alloc]init];
loginModel.emailAddr =emailTxt.text;
loginModel.password = passwordTxt.text;
[ASKevrOperationManager login:loginModel handler:^(id object , NSError *error ,
BOOL success)
{
if (success){
NSLog(#"object =%#",object);
NSDictionary *arr = [object objectForKey:#"response"];
str = [arr objectForKey:#"flag"];
//check for error
NSDictionary *toDict = [object objectForKey:#"response"];
currentUserId = [toDict objectForKey:#"c_id"];
NSLog(#"currentUserId = %#",currentUserId);
//perform the segue only when succesful
[self performSegueWithIdentifier:#"yourSegue" sender:sender];
}else{
[self showAlertWithMessage:#"Wrong Id or Password."];
}
}];
}else {
[self showAlertWithMessage:#"Please write your id or password"];
}
Keep your shouldPerformSegueWithIdentifier simple
-(BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender
{
if ([identifier isEqualToString:#"pushTab"])
{
//don't put logic here
//put code here only if you need to pass data
//to the next screen
return YES:
}
return NO;
}
Related
I want to include a "Sign Up using LinkedIn" feature in my app.
I'd like to be able to get some information, such as name and email.
By default I am able to get a name, but I'm stuck on getting the email.
My results are in JSON.
Here's my code:
- (IBAction)logInWithLinkedIn:(id)sender
{
if ([_client validToken])
{
[self requestMeWithToken:[_client accessToken]];
}
else
{
[_client getAuthorizationCode:^(NSString *code)
{
[self.client getAccessToken:code success:^(NSDictionary *accessTokenData) {
NSString *accessToken = [accessTokenData objectForKey:#"access_token"];
[self requestMeWithToken:accessToken];
} failure:^(NSError *error) {
NSLog(#"Quering accessToken failed %#", error);
}];
} cancel:^{
NSLog(#"Authorization was cancelled by user");
} failure:^(NSError *error) {
NSLog(#"Authorization failed %#", error);
}];
}
}
- (void)requestMeWithToken:(NSString *)accessToken
{
[self.client GET:[NSString stringWithFormat:#"https://api.linkedin.com/v1/people/~?oauth2_access_token=%#&format=json", accessToken] parameters:nil success:^(AFHTTPRequestOperation *operation, NSDictionary *result) {
NSLog(#"current user %#", result);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"failed to fetch current user %#", error);
}];
}
- (LIALinkedInHttpClient *)client
{
LIALinkedInApplication *application = [LIALinkedInApplication applicationWithRedirectURL:#"redirectURL"
clientId:#"key"
clientSecret:#"secret"
state:#"state"
grantedAccess:#[#"r_emailaddress"]];
return [LIALinkedInHttpClient clientForApplication:application presentingViewController:nil];
}
My result is:
firstName
headline
lastName
siteStandardProfileRequest
Anyone see how I can get the email?
You should use:
[self.client GET:[NSString stringWithFormat:#"https://api.linkedin.com/v1/people/~:(id,first-name,last-name,maiden-name,email-address)?oauth2_access_token=%#&format=json", accessToken] parameters:nil success:^(AFHTTPRequestOperation *operation, NSDictionary *result)
This may helps :)
You can use LinkedIn SDK
+ (void)loginToLinkedInAndFetchProfileData:(RequestResult)resultHandler
{
void (^PerformDataFetch)() = ^() {
if ([LISDKSessionManager hasValidSession]) {
NSString *urlString = [NSString stringWithFormat:#"%#/people/~:(id,first-name,last-name,maiden-name,email-address)", LINKEDIN_API_URL];
[[LISDKAPIHelper sharedInstance] getRequest:urlString success:^(LISDKAPIResponse *response) {
NSString *token = [[LISDKSessionManager sharedInstance].session.accessToken serializedString];
[[NSUserDefaults standardUserDefaults] setValue:token forKey:LinkedInAccessTokenKey];
[[NSUserDefaults standardUserDefaults] synchronize];
NSData *objectData = [response.data dataUsingEncoding:NSUTF8StringEncoding];
id value = [NSJSONSerialization JSONObjectWithData:objectData options:kNilOptions error:nil];
resultHandler(value, nil);
} error:^(LISDKAPIError *error) {
resultHandler(nil, error);
}];
}
};
NSString *token = [[NSUserDefaults standardUserDefaults] stringForKey:LinkedInAccessTokenKey];
if (token.length) {
LISDKAccessToken *accessToken = [LISDKAccessToken LISDKAccessTokenWithSerializedString:token];
if ([accessToken.expiration isLaterThan:[NSDate date]]) {
[LISDKSessionManager createSessionWithAccessToken:accessToken];
PerformDataFetch();
}
} else {
[LISDKSessionManager createSessionWithAuth:[NSArray arrayWithObjects:LISDK_BASIC_PROFILE_PERMISSION, LISDK_EMAILADDRESS_PERMISSION, nil] state:nil showGoToAppStoreDialog:YES successBlock:^(NSString *returnState) {
PerformDataFetch();
} errorBlock:^(NSError *error) {
resultHandler(nil, error);
}];
}
}
Response
> {
> emailAddress = "someEmail#email.com";
> firstName = Name;
> id = "2342d-6Y";
> lastName = LastName;
> }
Also this link can be useful
Update for Swift 3:
// Set preferred scope.
let scope = "r_basicprofile%20r_emailaddress"
// Then
if let accessToken = UserDefaults.standard.object(forKey: "LIAccessToken") {
// Specify the URL string that we'll get the profile info from.
let targetURLString = "https://api.linkedin.com/v1/people/~:(id,first-name,last-name,maiden-name,email-address)?format=json"
-(void)syncLinkedInWithCompetionHandler:(CompletionBlock)block{
[LISDKSessionManager createSessionWithAuth:[NSArray arrayWithObjects:LISDK_BASIC_PROFILE_PERMISSION, LISDK_EMAILADDRESS_PERMISSION, nil]
state:#"some state"
showGoToAppStoreDialog:YES
successBlock:^(NSString *returnState) {
NSLog(#"%s","success called!");
LISDKSession *session = [[LISDKSessionManager sharedInstance] session];
NSLog(#"value=%# \nisvalid=%#",[session value],[session isValid] ? #"YES" : #"NO");
block(returnState, nil);
}
errorBlock:^(NSError *error) {
NSLog(#"%s %#","error called! ", [error description]);
block(nil, error);
}
];
}
-(void)getProfileDataWithCompletion:(CompletionBlock)block {
NSString *urlString = [NSString stringWithFormat:#"%#/people/~:(id,first-name,last-name,headline,location,email-address)", LINKEDIN_API_URL];
NSLog(#"urlString = %#",urlString);
[[LISDKAPIHelper sharedInstance] getRequest:urlString success:^(LISDKAPIResponse *response) {
NSError *jsonError;
NSData *objectData = [response.data dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *responseDict = [NSJSONSerialization JSONObjectWithData:objectData
options:NSJSONReadingMutableContainers
error:&jsonError];
NSLog(#"responseDict = %#",responseDict);
block(responseDict, nil);
} error:^(LISDKAPIError *error) {
NSLog(#"error = %#",error);
block(error, nil);
}];
}
Hi I am very new to ios and in my app I am using NSUrlSession for integrating services.
Here my main problem is when I get a response from the server, I can't handle them properly.
When I get a correct response, then see the below json stucture:-
responseObject = {
{
Name = Broad;
DeptNo = A00;
BatchNo = 23;
DeptId = 120;
},
{
Name = James;
DeptNo = B00;
BatchNo = 23;
DeptId = 123;
},
}
when I get a wrong response, see the below json stucture:-
responseObject = {
error = 1;
message = "Invalid Code";
}
when I get a correct response from the server, I am getting an exception in my below if block(like __NSCFArray objectForKey:]: unrecognized selector sent to instance 0x1611c200') and when I get a wrong response then T get exception in my else block
Please help me how to handle them
my code:-
(void) GetCallService1: (id)MainResponse{
dispatch_async(dispatch_get_main_queue(), ^{
NameArray = [[NSMutableArray alloc]init];
IdArray = [[NSMutableArray alloc]init];
if([MainResponse objectForKey:#"error"] != nil)
{
NSLog(#"No data available");
}
else{
for (NSDictionary *obj in MainResponse) {
if([obj objectForKey:#"Name"] && [obj objectForKey:#"DeptNo"]) {
NSString * Name = [obj objectForKey:#"Name"];
[NameArray addObject:Name];
NSString * Id = [obj objectForKey:#"id"];
[IdArray addObject:Id];
}
}
}
});
}
1)Change Your implementation like below
2)I checked is it dictionary type & error key has some value
3)Earlier you were calling objectForKey on Array, therefore it was crashing
-(void) GetCallService1: (id)MainResponse{
dispatch_async(dispatch_get_main_queue(), ^{
NameArray = [[NSMutableArray alloc]init];
IdArray = [[NSMutableArray alloc]init];
//here I checked is it dictionary type & error key has some value
if ([MainResponse isKindOfClass:[NSDictionary class ]] &&[MainResponse objectForKey:#"error"])
{
NSLog(#"No data available");
}
else{
for (NSDictionary *obj in MainResponse) {
if([obj objectForKey:#"Name"] && [obj objectForKey:#"DeptNo"]) {
NSString * Name = [obj objectForKey:#"Name"];
[NameArray addObject:Name];
NSString * Id = [obj objectForKey:#"id"];
[IdArray addObject:Id];
}
}
}
});
}
Try this:
//Result Block
typedef void (^ResultBlock)(id, NSError*);
//URL request
-(void)requestURL:(NSURLRequest *)request withResult:(ResultBlock)resultHandler{
//URLSession
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * data, NSURLResponse * response, NSError * error) {
if(!error){
NSError *jsonError = nil;
id result = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&jsonError];
if([result isKindOfClass:[NSArray class]]){
//Success
resultHandler(result,nil);
}
else if([result isKindOfClass:[NSDictionary class]]){
if([[result objectForKey:#"error"] integerValue]){
//Failure.
NSMutableDictionary *errorDetail = [NSMutableDictionary dictionary];
[errorDetail setValue:[result objectForKey:#"message"] forKey:NSLocalizedDescriptionKey];
NSError *error = [NSError errorWithDomain:#"Error" code:100 userInfo:errorDetail];
resultHandler(nil, errorDetail);
}
}
}
}];
[task resume];
}
//Call your requestURL method:
[self requestURL:request withResult:^(id result, NSError *error){
if(!error){
//Success, Read & update your list
}
else{
//Error
// NSLog(error.localizedDescription());
}
}];
How can i URLEncode a NSDictionary so i can send it across AFNetworking.
The code is as follows:
NSMutableDictionary *rus = [[NSMutableDictionary alloc] init];
[rus setValue:#"1211" forKey:#"id"];
[rus setValue:#"33" forKey:#"man"];
How can i Encode this NSDictionary so i can send it across AFNetworking ?
Depends how you wish to send your data:
1) #"application/json" in which case you would use [NSJSONSerialization dataWithJSONObject:parameters options:self.writingOptions error:error]
2) #"application/x-www-form-urlencoded" in which case you basically want to create the string: ?id=1211&man=33 from your dictionary rus.
Here's some code, may not be the most efficient by you get the idea:
NSString *temp;
int i=0;
for(NSString *key in options.params.allKeys)
{
NSString *value = [options.params objectForKey:key];
[parameters setObject:value forKey:key];
if(i==0)
{
temp = [NSString stringWithFormat:#"?%#=%#", key,value];
}
else
{
temp = [NSString stringWithFormat:#"%#&%#=%#", temp, key, value];
}
}
Note: may or may not be relevant to you, but my two cents:
I use AFHTTPSessionManager which handles all the details for me including url encoding, so I just pass in the desired dictionary:
NSMutableDictionary *rus = [[NSMutableDictionary alloc] init];
[rus setValue:#"1211" forKey:#"id"];
[rus setValue:#"33" forKey:#"man"];
[self POST:#"/api/place/nearbysearch" parameters:rus success:^(NSURLSessionDataTask *task, id responseObject) {
NSLog(#"nearbyPlaces: success");
[self fetchedPlacesData:responseObject block:block];
if(task != nil && task.originalRequest != nil)
{
NSString *url = [task.originalRequest.URL absoluteString];
[self saveNearbySearchEvent:url params:params];
}
} failure:^(NSURLSessionDataTask *task, NSError *error) {
NSLog(#"nearbyPlaces: error: %#", error);
block(self, nil, error);
}];
AFHTTPSessionManager encapsulates a lot of functionality included serializing the data: AFURLRequestSerialization either as JSON or HTTP Request. In case you interested on what AFHTTPSessionManager actually does here's some detail:
A) HTTP Request
Here's the code from AFURLRequestSerialization.m:
- (NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request
withParameters:(id)parameters
error:(NSError *__autoreleasing *)error
{
NSParameterAssert(request);
NSMutableURLRequest *mutableRequest = [request mutableCopy];
[self.HTTPRequestHeaders enumerateKeysAndObjectsUsingBlock:^(id field, id value, BOOL * __unused stop) {
if (![request valueForHTTPHeaderField:field]) {
[mutableRequest setValue:value forHTTPHeaderField:field];
}
}];
if (parameters) {
NSString *query = nil;
if (self.queryStringSerialization) {
NSError *serializationError;
query = self.queryStringSerialization(request, parameters, &serializationError);
if (serializationError) {
if (error) {
*error = serializationError;
}
return nil;
}
} else {
switch (self.queryStringSerializationStyle) {
case AFHTTPRequestQueryStringDefaultStyle:
query = AFQueryStringFromParametersWithEncoding(parameters, self.stringEncoding);
break;
}
}
if ([self.HTTPMethodsEncodingParametersInURI containsObject:[[request HTTPMethod] uppercaseString]]) {
mutableRequest.URL = [NSURL URLWithString:[[mutableRequest.URL absoluteString] stringByAppendingFormat:mutableRequest.URL.query ? #"&%#" : #"?%#", query]];
} else {
if (![mutableRequest valueForHTTPHeaderField:#"Content-Type"]) {
[mutableRequest setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
}
[mutableRequest setHTTPBody:[query dataUsingEncoding:self.stringEncoding]];
}
}
return mutableRequest;
}
B) JSON
- (NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request
withParameters:(id)parameters
error:(NSError *__autoreleasing *)error
{
NSParameterAssert(request);
if ([self.HTTPMethodsEncodingParametersInURI containsObject:[[request HTTPMethod] uppercaseString]]) {
return [super requestBySerializingRequest:request withParameters:parameters error:error];
}
NSMutableURLRequest *mutableRequest = [request mutableCopy];
[self.HTTPRequestHeaders enumerateKeysAndObjectsUsingBlock:^(id field, id value, BOOL * __unused stop) {
if (![request valueForHTTPHeaderField:field]) {
[mutableRequest setValue:value forHTTPHeaderField:field];
}
}];
if (parameters) {
if (![mutableRequest valueForHTTPHeaderField:#"Content-Type"]) {
[mutableRequest setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
}
[mutableRequest setHTTPBody:[NSJSONSerialization dataWithJSONObject:parameters options:self.writingOptions error:error]];
}
return mutableRequest;
}
NSMutableDictionary *rus = [[NSMutableDictionary alloc] init];
[rus setValue:#"1211" forKey:#"id"];
[rus setValue:#"33" forKey:#"man"];
If you are exchanging JSON data with your server:
NSError *error = nil;
NSData *aRequestData = [NSJSONSerialization dataWithJSONObject:rus options:NSJSONWritingPrettyPrinted error:&error];
if (!error) {
[urlRequest setHTTPBody:aRequestData];
}
If you are exchanging PLIST data with your server:
[self stringByAppendingQueryParameters:rus appendQuestionMark:NO];
- (NSString *)stringByAppendingQueryParameters:(NSDictionary *)iParameters appendQuestionMark:(BOOL)iAppendQuestionMark {
BOOL aAppendAmpersand = YES;
NSMutableString *aWorking = [NSMutableString stringWithString:self];
if (iAppendQuestionMark) {
NSRange aQueryBeginning = [self rangeOfString:#"?"];
if (aQueryBeginning.location == NSNotFound) {
[aWorking appendString:#"?"];
aAppendAmpersand = NO;
}
} else {
aAppendAmpersand = NO;
}
for (id aKey in iParameters) {
id aValue = [iParameters valueForKey:aKey];
NSString *aKeyStr = [self convertObjectToURLEncodedValue:aKey];
if (aAppendAmpersand) {
[aWorking appendString:#"&"];
} else {
aAppendAmpersand = YES;
}
if ([aValue isKindOfClass:[NSArray class]]) {
NSArray *aSubParamaters = (NSArray *)aValue;
BOOL aFirstTime = YES;
for (id aSubValue in aSubParamaters) {
NSString *aValueString = [self convertObjectToURLEncodedValue:aSubValue];
if (!aFirstTime) {
[aWorking appendString:#"&"];
}
[aWorking appendString:aKeyStr];
[aWorking appendString:#"="];
[aWorking appendString:aValueString];
aFirstTime = NO;
}
} else {
NSString *aValueString = [self convertObjectToURLEncodedValue:aValue];
[aWorking appendString:aKeyStr];
[aWorking appendString:#"="];
[aWorking appendString:aValueString];
}
}
return [NSString stringWithString:aWorking];
}
- (NSString *)convertObjectToURLEncodedValue:(id)iObject {
NSString *anIntermediate = nil;
if ([iObject isKindOfClass:[NSString class]]) {
anIntermediate = iObject;
} else if ([iObject respondsToSelector:#selector(stringValue)]) {
anIntermediate = [iObject stringValue];
} else {
anIntermediate = [iObject description];
}
NSString *anEncodingString = (__bridge_transfer NSString *)(CFURLCreateStringByAddingPercentEscapes(
NULL,
(__bridge CFStringRef)anIntermediate,
NULL,
(CFStringRef)#"!*'();:#&=+$,/?%#[]",
kCFStringEncodingUTF8 ));
return anEncodingString;
}
I want to include a "Sign Up using LinkedIn" feature in my app.
I'd like to be able to get some information, such as name and email.
By default I am able to get a name, but I'm stuck on getting the email.
My results are in JSON.
Here's my code:
- (IBAction)logInWithLinkedIn:(id)sender
{
if ([_client validToken])
{
[self requestMeWithToken:[_client accessToken]];
}
else
{
[_client getAuthorizationCode:^(NSString *code)
{
[self.client getAccessToken:code success:^(NSDictionary *accessTokenData) {
NSString *accessToken = [accessTokenData objectForKey:#"access_token"];
[self requestMeWithToken:accessToken];
} failure:^(NSError *error) {
NSLog(#"Quering accessToken failed %#", error);
}];
} cancel:^{
NSLog(#"Authorization was cancelled by user");
} failure:^(NSError *error) {
NSLog(#"Authorization failed %#", error);
}];
}
}
- (void)requestMeWithToken:(NSString *)accessToken
{
[self.client GET:[NSString stringWithFormat:#"https://api.linkedin.com/v1/people/~?oauth2_access_token=%#&format=json", accessToken] parameters:nil success:^(AFHTTPRequestOperation *operation, NSDictionary *result) {
NSLog(#"current user %#", result);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"failed to fetch current user %#", error);
}];
}
- (LIALinkedInHttpClient *)client
{
LIALinkedInApplication *application = [LIALinkedInApplication applicationWithRedirectURL:#"redirectURL"
clientId:#"key"
clientSecret:#"secret"
state:#"state"
grantedAccess:#[#"r_emailaddress"]];
return [LIALinkedInHttpClient clientForApplication:application presentingViewController:nil];
}
My result is:
firstName
headline
lastName
siteStandardProfileRequest
Anyone see how I can get the email?
You should use:
[self.client GET:[NSString stringWithFormat:#"https://api.linkedin.com/v1/people/~:(id,first-name,last-name,maiden-name,email-address)?oauth2_access_token=%#&format=json", accessToken] parameters:nil success:^(AFHTTPRequestOperation *operation, NSDictionary *result)
This may helps :)
You can use LinkedIn SDK
+ (void)loginToLinkedInAndFetchProfileData:(RequestResult)resultHandler
{
void (^PerformDataFetch)() = ^() {
if ([LISDKSessionManager hasValidSession]) {
NSString *urlString = [NSString stringWithFormat:#"%#/people/~:(id,first-name,last-name,maiden-name,email-address)", LINKEDIN_API_URL];
[[LISDKAPIHelper sharedInstance] getRequest:urlString success:^(LISDKAPIResponse *response) {
NSString *token = [[LISDKSessionManager sharedInstance].session.accessToken serializedString];
[[NSUserDefaults standardUserDefaults] setValue:token forKey:LinkedInAccessTokenKey];
[[NSUserDefaults standardUserDefaults] synchronize];
NSData *objectData = [response.data dataUsingEncoding:NSUTF8StringEncoding];
id value = [NSJSONSerialization JSONObjectWithData:objectData options:kNilOptions error:nil];
resultHandler(value, nil);
} error:^(LISDKAPIError *error) {
resultHandler(nil, error);
}];
}
};
NSString *token = [[NSUserDefaults standardUserDefaults] stringForKey:LinkedInAccessTokenKey];
if (token.length) {
LISDKAccessToken *accessToken = [LISDKAccessToken LISDKAccessTokenWithSerializedString:token];
if ([accessToken.expiration isLaterThan:[NSDate date]]) {
[LISDKSessionManager createSessionWithAccessToken:accessToken];
PerformDataFetch();
}
} else {
[LISDKSessionManager createSessionWithAuth:[NSArray arrayWithObjects:LISDK_BASIC_PROFILE_PERMISSION, LISDK_EMAILADDRESS_PERMISSION, nil] state:nil showGoToAppStoreDialog:YES successBlock:^(NSString *returnState) {
PerformDataFetch();
} errorBlock:^(NSError *error) {
resultHandler(nil, error);
}];
}
}
Response
> {
> emailAddress = "someEmail#email.com";
> firstName = Name;
> id = "2342d-6Y";
> lastName = LastName;
> }
Also this link can be useful
Update for Swift 3:
// Set preferred scope.
let scope = "r_basicprofile%20r_emailaddress"
// Then
if let accessToken = UserDefaults.standard.object(forKey: "LIAccessToken") {
// Specify the URL string that we'll get the profile info from.
let targetURLString = "https://api.linkedin.com/v1/people/~:(id,first-name,last-name,maiden-name,email-address)?format=json"
-(void)syncLinkedInWithCompetionHandler:(CompletionBlock)block{
[LISDKSessionManager createSessionWithAuth:[NSArray arrayWithObjects:LISDK_BASIC_PROFILE_PERMISSION, LISDK_EMAILADDRESS_PERMISSION, nil]
state:#"some state"
showGoToAppStoreDialog:YES
successBlock:^(NSString *returnState) {
NSLog(#"%s","success called!");
LISDKSession *session = [[LISDKSessionManager sharedInstance] session];
NSLog(#"value=%# \nisvalid=%#",[session value],[session isValid] ? #"YES" : #"NO");
block(returnState, nil);
}
errorBlock:^(NSError *error) {
NSLog(#"%s %#","error called! ", [error description]);
block(nil, error);
}
];
}
-(void)getProfileDataWithCompletion:(CompletionBlock)block {
NSString *urlString = [NSString stringWithFormat:#"%#/people/~:(id,first-name,last-name,headline,location,email-address)", LINKEDIN_API_URL];
NSLog(#"urlString = %#",urlString);
[[LISDKAPIHelper sharedInstance] getRequest:urlString success:^(LISDKAPIResponse *response) {
NSError *jsonError;
NSData *objectData = [response.data dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *responseDict = [NSJSONSerialization JSONObjectWithData:objectData
options:NSJSONReadingMutableContainers
error:&jsonError];
NSLog(#"responseDict = %#",responseDict);
block(responseDict, nil);
} error:^(LISDKAPIError *error) {
NSLog(#"error = %#",error);
block(error, nil);
}];
}
This seems such an easy task, at least it is in VB.net. I simply need to reference an array based on a string that is passed to a method. When a view controller loads a method is called and a string is passed. A URL will be created based on this string and JSON will be fetched from it. What I want is for the method to populate an appropriate array based on this passed string.
Here we see the method "goGetData" being called in class "getData" with one of three string parameters "workshop/speaker/exhibitor":
- (void)viewDidLoad
{
[getData goGetData:#"workshop"];
[getData goGetData:#"speaker"];
[getData goGetData:#"exhibitor"];
getData *getDataInstance = [[getData alloc] init];
NSArray *newTablesArray = getDataInstance.jsonAllTables;
NSLog(#"Json currently = %#", newTablesArray);
[super viewDidLoad];
[[self myTableView]setDelegate:self];
[[self myTableView]setDataSource:self];
arrayTable =[[NSMutableArray alloc]init];
}
For example if "goGetDate" is fired with "speaker" I would need the speaker data to be fetched and then the "_jsonSpeaker" array to be populated. Here is my attempt so far to reference and populate the arrays based on what string was passed in the method call:
#import "getData.h"
#implementation getData
+(void)goGetData:(NSString *)requestedTable
{
getData *getDataInstance = [[getData alloc] init];
[getDataInstance buildArray];
[getDataInstance fetchData:requestedTable];
}
-(void)buildArray{
// I tried putting the arrays in an array but still do no know how to reference them
_jsonAllTables = [[NSMutableArray alloc] initWithObjects:_jsonExhibitor, _jsonSpeaker, _jsonWorkshop, nil];
}
-(void)fetchData:(NSString *)requestedTable{
NSString *varCurrentTable;
varCurrentTable = [NSString stringWithFormat:#"_json%#", requestedTable];
NSString *requestedURL;
requestedURL = [NSString stringWithFormat:#"http://testapi.website.com/api/%#", requestedTable];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:requestedURL]];
[NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
{
if (response){
NSHTTPURLResponse *newResp = (NSHTTPURLResponse*)response;
if (newResp.statusCode == 200) {
// STUFF FOR TESTING NSLog(#"Response to request: %# is: %i GOOD", requestedURL, newResp.statusCode);
if ([data length] >0 && error == nil)
{
// STUFF FOR TESTING NSUInteger indexOfArray = [_jsonAllTables indexOfObject:varCurrentTable];
// STUFF FOR TESTING NSString *objectAtIndexOfArray = [_jsonAllTables objectAtIndex:indexOfArray];
// This is the part I think I am stuck on:
// "CURRENT TABLE TO BE POPULATED" = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
}
else if ([data length] == 0 && error == nil)
{
NSLog(#"Nothing was downloaded");
}
else if (error != nil)
{
NSLog(#"Error: %#", error);
}
} else if (newResp.statusCode == 404){
NSLog(#"Response to request: %# is: %i BAD - URL incorrect", requestedURL, newResp.statusCode);
} else {
// add more returned status error handling here
}
}else{
NSLog(#"No response received");
}
}];
}
#end
Thanks,
Added for clarification on what I am trying to achieve: To save a LOT of writing out the same thing over and over is the following possibly in Obj-c (please excuse the mish-mash of languages)
NSArray *ListOfTables = [NSArray arrayWithObjects:#"Speaker", #"Exhibitor", #"Workshop", nil];
For i as int = 0 to ListOfTables.count{
[self fetchData:(ListOfTables.objectAtIndex = i) withCompletion:^(NSArray* objects, NSError*error){
dispatch_async(dispatch_get_main_queue(), ^{
if (objects) {
self.(ListOfTables.objectAtIndex = i) = objects;
}
else {
NSLog(#"Error: %error", error);
}
});
}];
i++;
Next
};
Notice i don't call a separate method for each table, instead I call the same method but with different table name parameter each time. I can't seem to find a working example with such placeholders in Xcode.
You probably want a method which is asynchronous and returns the result via a completion handler:
typedef void(^completion_t)(NSArray* objects, NSError*error);
-(void)fetchData:(NSString *)tableName
withCompletion:(completion_t)completionHandler;
Usage:
- (void) foo {
[self fetchData:tableName1 withCompletion:^(NSArray* objects, NSError*error){
dispatch_async(dispatch_get_main_queue(), ^{
if (objects) {
self.table1 = objects;
}
else {
NSLog(#"Error: %error", error);
}
});
}];
[self fetchData:tableName2 withCompletion:^(NSArray* objects, NSError*error){
dispatch_async(dispatch_get_main_queue(), ^{
if (objects) {
self.table2 = objects;
}
else {
NSLog(#"Error: %error", error);
}
});
}];
[self fetchData:tableName3 withCompletion:^(NSArray* objects, NSError*error){
dispatch_async(dispatch_get_main_queue(), ^{
if (objects) {
self.table3 = objects;
}
else {
NSLog(#"Error: %error", error);
}
});
}];
}
Implementation:
typedef void(^completion_t)(NSArray* objects, NSError* error);
-(void)fetchData:(NSString *)tableName
withCompletion:(completion_t)completionHandler
{
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:tableName]];
// Setup HTTP headers, e.g. "Accept: application/json", etc.
...
[NSURLConnection sendAsynchronousRequest:request
queue:[[NSOperationQueue alloc] init]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
{
NSError* err = error;
NSArray* objects; // final result array as a representation of JSON Array
if (response) {
NSHTTPURLResponse *newResp = (NSHTTPURLResponse*)response;
if (newResp.statusCode == 200) {
if ([data length] >0 && error == nil)
{
NSError* localError;
objects = ... // Use NSJSONSerialization to obtain a representation
if (objects) {
if (completionHandler) {
completionHandler(object, nil);
}
return;
}
else {
err = localError;
}
}
else {
err = ...
}
}
}
if (objects == nil) {
assert(err);
if (completionHandler) {
completionHandler(nil, err);
}
}
}];
}
Asynchronous Loop
Another example, for loading a bunch of data:
First, implemented a method which is an "asynchronous loop":
typedef void(^completion_t)(id result, NSError* error);
- (void) fetchObjectsWithTableNames:(NSMutableArray*)tableNames
completion:(completion_t)completionHandler;
This method is, itself asynchronous, thus the completion handler.
Usage:
- (void) foo
{
NSArray* tableNames = #[#"A", #"B", #"C"]; // possibly 1000
[self fetchObjectsWithTableNames:[tableNames mutableCopy]:^(id result, NSError*error){
if (error) {
NSLog(#"Error: %#", error);
}
else {
// finished fetching a bunch of datas with result:
NSLog(#"Result: %#", result);
}
}];
}
Implementation
- (void) fetchObjectsWithTableNames:(NSMutableArray*)tableNames
completion:(completion_t)completionHandler;
{
if ([tableNames count] > 0) {
NSString* name = [tableNames firstObject];
[tableNames removeObjectAtIndex:0];
[self fetchData:name withCompletion:^(NSArray* objects, NSError*error){
if (objects) {
[self.tables addObject:objects];
[self fetchObjectsWithTableNames:tableNames completion:completionHandler];
}
else {
// handle error
}
}];
}
else {
// finished
if (completionHandler) {
completionHandler(#"finished", nil);
}
}
}