Google OAuth Suddenly Not Working AFNetworkingErrorDomain - ios

This past week the Google OAuth portion of my iOS app has completely stopped working out of nowhere. The user enters their details into the custom login field within the app, which then authorizes with Google, creates a token, and should tell them that their login has been successful (within the app). Instead, they are seeing a Login Failed message. I cannot seem to figure out why (did Google change something??) but the error code I am getting when users try to login is the following:
2013-10-27 12:49:56.137 XXXX [1210:1a003] URL is https://accounts.google.com/o/oauth2/approval?as=1e543c0fe20b1da5&hl=en_GB&pageId=none&xsrfsign=APsBz4gAAAAAUm1LHD2mXAhs8QexAFwlf9KVIt5UdNj_
2013-10-27 12:49:57.776 XXXX[1210:1a003] 333
2013-10-27 12:49:57.776 XXXX[1210:1a003] Failed: -1011
2013-10-27 12:49:57.777 XXXX[1210:1a003] Description: Error
Domain=AFNetworkingErrorDomain Code=-1011 "Expected status code in (200-299), got 400"
UserInfo=0x96b5700 {NSLocalizedRecoverySuggestion=<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML
4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><title>Google
Accounts</title><meta http-equiv="content-type" content="text/html; charset=utf-8"><meta
name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-
scale=1, user-scalable=0" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><link
rel='stylesheet' type='text/css' href='https://ssl.gstatic.com/accounts/o/1893590695-error_page_css_ltr.css'>
<script type="text/javascript" src="https://ssl.gstatic.com/accounts/o/708588620-common_lib.js"></script>
<style>#media screen and (max-width:500px) {#robot {background: none; min-height: 0; min-width: 0; padding: 0;}#stack_trace {display: none;}}
#oauth2_request_info_header {background-image: url("https://ssl.gstatic.com/accounts/o/blank.gif");}</style></head><body ><div id="robot"></div><img src="//www.google.com/images/logo_sm.gif" alt="Google"><p class="large"><b>400.</b> <ins>That's an error.</ins></p><p class="large">The page that you requested is invalid. <ins>That's all we know.</ins></p></body></html>, AFNetworkingOperationFailingURLRequestErrorKey=<NSMutableURLRequest https://accounts.google.com/o/oauth2/approval?as=1e543c0fe20b1da5&hl=en_GB&pageId=none&xsrfsign=APsBz4gAAAAAUm1LHD2mXAhs8QexAFwlf9KVIt5UdNj_>, NSErrorFailingURLKey=https://accounts.google.com/o/oauth2/approval?as=1e543c0fe20b1da5&hl=en_GB&pageId=none&xsrfsign=APsBz4gAAAAAUm1LHD2mXAhs8QexAFwlf9KVIt5UdNj_, NSLocalizedDescription=Expected status code in (200-299), got 400, AFNetworkingOperationFailingURLResponseErrorKey=<NSHTTPURLResponse: 0x96aae40>}
Here are the parts of the code that seem to be causing the error:
-(void)doSignInStep2:(NSString*)response
{
// NSLog(#"RESPONSE: %#", response);
NSString *form = [response substringFromIndex:[response rangeOfString:#"form "].location];
form = [form substringToIndex:[form rangeOfString:#"</form>"].location];
NSString *formAction = [form substringFromIndex:[form rangeOfString:#"action="].location + 8];
formAction = [formAction substringToIndex:[formAction rangeOfString:#"\""].location];
if ([formAction rangeOfString:#"'"].location != NSNotFound)
{
formAction = [formAction substringToIndex:[formAction rangeOfString:#"'"].location];
}
formAction = [formAction stringByReplacingOccurrencesOfString:#"&" withString:#"&"];
//get all input elements in the form
NSMutableArray *elements = [[NSMutableArray alloc] init];
NSRange rng = [form rangeOfString:#"<input "];
while (rng.location != NSNotFound)
{
NSString *inputItem = [form substringFromIndex:rng.location];
NSInteger *inputItemLength = [inputItem rangeOfString:#">"].location + 1;
inputItem = [inputItem substringToIndex:inputItemLength];
NSString *elementName = nil;
NSString *elementValue = nil;
NSRange iiRange = [inputItem rangeOfString:#"name=\""];
if (iiRange.location != NSNotFound) {
elementName = [inputItem substringFromIndex:iiRange.location + 6];
elementName = [elementName substringToIndex:[elementName rangeOfString:#"\""].location];
}
iiRange = [inputItem rangeOfString:#"value=\""];
if (iiRange.location != NSNotFound) {
elementValue = [inputItem substringFromIndex:iiRange.location + 7];
elementValue = [elementValue substringToIndex:[elementValue rangeOfString:#"\""].location];
elementValue = [elementValue stringByReplacingOccurrencesOfString:#"&" withString:#"&"];
}
if (elementName && elementValue) {
NSString *encodedstring = (__bridge NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,
(__bridge CFStringRef)elementValue,
NULL,
(CFStringRef)#"!*'();:#&=+$,/?%#[]",
kCFStringEncodingUTF8);
if (![elementName isEqualToString:#"submit_access"])
[elements addObject:[NSMutableArray arrayWithObjects:elementName, encodedstring, nil]];
}
form = [form substringFromIndex:rng.location];
form = [form substringFromIndex:inputItemLength];
rng = [form rangeOfString:#"<input "];
}
[elements addObject:[NSMutableArray arrayWithObjects:#"submit_access", #"true", nil]];
NSString *params = #"";
for (int i = 0; i < [elements count]; i++)
{
NSMutableArray *element = [elements objectAtIndex:i];
if ([params length] > 0)
params = [params stringByAppendingString:#"&"];
params = [params stringByAppendingString:[element objectAtIndex:0]];
params = [params stringByAppendingString:#"="];
params = [params stringByAppendingString:[element objectAtIndex:1]];
}
//NSLog(#"Params: %#", params);
NSURL *url = [NSURL URLWithString:formAction];
NSLog(#"URL is %#", url);
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setCachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData];
[request setHTTPMethod:#"POST"];
[request setHTTPBody:[params dataUsingEncoding:NSUTF8StringEncoding]];
//[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
//[request setValue:[params length] forHTTPHeaderField:#"Content-Length"];
AFHTTPRequestOperation *op3 = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[op3 setCompletionBlockWithSuccess: ^(AFHTTPRequestOperation *operation, NSError *error) {
NSString *response = [[NSString alloc] initWithData:operation.responseData encoding:NSUTF8StringEncoding];
[self doSignInStep3:response];
}failure: ^(AFHTTPRequestOperation *operation, NSError *error)
{
NSLog(#"333");
NSLog(#"Failed: %d", error.code);
NSLog(#"Description: %#", error.description);
//NSLog(#"Response: %#", [[NSString alloc] initWithData:operation.responseData encoding:NSUTF8StringEncoding]);
[self.delegate finishedSignIn:[NSNumber numberWithBool:NO] response:nil];
}];
[op3 start];
}
and...
-(void)doSignInStep3:(NSString*)response
{
//NSLog(#"Response: %#", response);
//<input id="code" type="text" readonly="readonly" value="4/Zvd-PjWHw53BqdSzExYus1MsT9dx.snLL4gUE1cocOl05ti8ZT3bZAne4dgI"
if ([response rangeOfString:#"<input id=\""].location == NSNotFound)
{
[self.delegate finishedSignIn:[NSNumber numberWithBool:NO] response:nil];
}
else
{
NSString *code = [response substringFromIndex:[response rangeOfString:#"<input id=\""].location];
code = [code substringFromIndex:[code rangeOfString:#"value=\""].location + 7];
code = [code substringToIndex:[code rangeOfString:#"\""].location];
NSURL *url = [NSURL URLWithString:#"https://accounts.google.com/o/oauth2/token"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setCachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData];
[request setHTTPMethod:#"POST"];
//NSLog(#"Code: %#", code);
NSString *params = [NSString stringWithFormat:#"code=%#", code];
params = [params stringByAppendingString:[NSString stringWithFormat:#"&client_id=%#", client_id]];
params = [params stringByAppendingString:[NSString stringWithFormat:#"&client_secret=%#", client_secret]];
params = [params stringByAppendingString:#"&redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob"];
params = [params stringByAppendingString:#"&grant_type=authorization_code"];
//params = [params stringByAppendingString:#"&approval_prompt=force"];
[request setHTTPBody:[params dataUsingEncoding:NSUTF8StringEncoding]];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
AFHTTPRequestOperation *op4 = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[op4 setCompletionBlockWithSuccess: ^(AFHTTPRequestOperation *operation, NSError *error) {
NSString *response = [[NSString alloc] initWithData:operation.responseData encoding:NSUTF8StringEncoding];
//NSLog(#"Response: %#", response);
[self processResponse:response];
[self.delegate finishedSignIn:[NSNumber numberWithBool:YES] response:response];
}failure: ^(AFHTTPRequestOperation *operation, NSError *error)
{
NSLog(#"444");
NSLog(#"Failed: %d", error.code);
NSLog(#"Description: %#", error.description);
//NSLog(#"Response: %#", [[NSString alloc] initWithData:operation.responseData encoding:NSUTF8StringEncoding]);
[self.delegate finishedSignIn:[NSNumber numberWithBool:NO] response:nil];
}];
[op4 start];
}
}
I am at a complete loss here because everything was totally fine previously and nothing was touched on my end. What would cause this to completely stop working? I've already tried new client_id and client_secret codes and they produce the same error. Any type of insight would be great.

Looking at the error page that you included in your logs, I see
The page that you requested is invalid. That's all we know.
My app is a webserver app, but I often see the same error page thrown up during authorisation. In my case, I simply Back and retry.
My working assumption is that it's a transient exception thrown somewhere in Google's infrastructure, which materialises in a misleading/meaningless error message.
So for your app, all I can suggest is that you somehow capture that situation and retry the login.

Related

Objective C setting labels after api call

UPDATE
I am making an api call getPacks() and successfully getting the values of two variables _numberOfPacks and _numberOfAutoRefills.
However, when I try to put it in a label it fails and gives output as (null) Packs & (null) Autorefiils
the calls are made in the following order:
getpacks()-------first (it sets value on _numberOfPacks and _numberOfAutoRefills as global variables
drawQuantity()-----set _numberOfPacks and _numberOfAutoRefills on labels.
-(void) getPacks: (IHPlacedOrder*)order{
NSOperationQueue *networkQueue = [[NSOperationQueue alloc] init];
networkQueue.maxConcurrentOperationCount = 5;
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"https://XXXXXXX.XXXXX/%#",order.ID]];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc]
initWithRequest:request];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSString *string = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
if([string isEqualToString:#""]){
} else {
NSMutableDictionary *dict=[NSJSONSerialization JSONObjectWithData:[string dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:nil];
NSLog(#"%#",dict);
_numberOfPacks = [[dict objectForKey:#"prescription_interval"] valueForKey:#"quantity_per_interval"];
_numberOfAutoRefills = [[dict objectForKey:#"prescription_interval"]valueForKey:#"num_intervals"];
NSLog(#"PACKS:%# , AUTOREFILLS:%#",_numberOfPacks,_numberOfAutoRefills);
_quantity.text = [NSString stringWithFormat: #"%#,%#",_numberOfPacks,_numberOfAutoRefills];
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"%s: AFHTTPRequestOperation error: %#", __FUNCTION__, error);
}];
[networkQueue addOperation:operation];
}
followed by:
-(void)drawQuantity: (IHPlacedOrder*)order{
PPLinearLayoutLabelItem *quantityLabel = [[PPLinearLayoutLabelItem alloc] initWithText:[NSString stringWithFormat:#"%# QUANTITY & %# REFILLS", _numberOfPacks,_numberOfAutoRefills] font:[PPFonts regular18] maxWidth:[LayoutValues getMaxWidthClipped]];
[quantityLabel setPaddingBottom:5];
[quantityLabel setPaddingTop:20];
[self.topContainerContent addObject:quantityLabel];
NSString* quantityText = [NSString stringWithFormat:#"Packs + Autorefills"];
PPLinearLayoutLabelItem *quantity = [[PPLinearLayoutLabelItem alloc] initWithText:quantityText font:[PPFonts genericParagraphFontBold] maxWidth:[LayoutValues getMaxWidthClipped]];
[quantity setPaddingBottom:20];
[self.topContainerContent addObject:quantity];
LinearLayoutHorizontalLine *line1 = [[LinearLayoutHorizontalLine alloc] initWithMaxWidth:[LayoutValues getMaxWidthClipped]];
[self.topContainerContent addObject:line1];
}
I found the solution. I was using wrong method call to set labels. The thing is my application uses PPLinearLayoutLabelItem as a custom built label. I had to call [self.quantity setLabel:#"%#",data_fromapi] to make it work. setText would just set the text within PPLinearLayoutLabelItem class and not set the Label.

Disqualify lead in Dynamics CRM (iOS)

How can i disqualify lead in Microsoft Dynamics CRM ? Is there any particular API for doing this from iOS platform?
I tried this :
for (id key in [details allKeys]) {
if([key isEqualToString:#"LeadState"])
{
[contactPostDict setObject:#"2" forKey:#"State"];
}
else if([key isEqualToString:#"LeadStatus"])
{
[contactPostDict setObject:#"6" forKey:#"Status"];
}
}
This is the error:
"error": {
"code": "", "message": {
"lang": "en-US", "value": "Error processing request stream. The property name 'Status' specified for type 'Microsoft.Crm.Sdk.Data.Services.Lead' is not valid."
}
}
I have never worked on the iOS platform but from the error that is being thrown, the error seems to be pretty straight forward.
You are looking for the keys "Status" & "State" but they don't exist. Instead you should be looking at their schema names which is as follows
Status = statuscode, State = statecode
Can you try modifying the code to use the above keys and see if you still gets the same error.
(BOOL)setLeadStatus:(NSString *)ID andDetails:(NSMutableDictionary *)details
{
NSString *uri = [MSDYNAMICS_AUTHENTICATION_CALL stringByAppendingPathComponent:[NSString stringWithFormat:#"LeadSet(guid'%#')/",ID]];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:uri]];
request.HTTPMethod = #"MERGE";
[request setValue:JSON_CONTENT_TYPE_PARAMETER forHTTPHeaderField:#"Content-Type"];
[request setValue:JSON_CONTENT_TYPE_PARAMETER forHTTPHeaderField:#"Accept"];
NSMutableDictionary *contactPostDict=[[NSMutableDictionary alloc]init];
for (id key in [details allKeys]) {
if([key isEqualToString:#"LeadState"])
{
[contactPostDict setObject:#"2" forKey:#"statecode"];
}
else if([key isEqualToString:#"LeadStatus"])
{
[contactPostDict setObject:#"6" forKey:#"statuscode"];
}
}
NSError *err;
NSData *postData=[NSJSONSerialization dataWithJSONObject:contactPostDict options:NSJSONWritingPrettyPrinted error:&err];
NSString* postString = [[NSString alloc] initWithData:postData encoding:NSUTF8StringEncoding];
//NSString *postString = #"";
[request setValue:JSON_CONTENT_TYPE_PARAMETER forHTTPHeaderField:CONTENT_TYPE_PARAMETER];
[request setHTTPBody:[postString dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES]];
SURLConnection *conn = [[SURLConnection alloc] init];
NSData *responseData = [conn sendSynchronousRequest:request returningResponse:nil error:nil];
NSString *err1 = [[NSString alloc]initWithData:responseData encoding:NSUTF8StringEncoding];
NSLog(#"error: %#",err1);
if(responseData.length==0 && [conn.response statusCode] == 204)
{
[self getLeadDetailsForID:ID];
return YES;
}
else{
NSString *err = [[NSString alloc]initWithData:responseData encoding:NSUTF8StringEncoding];
NSLog(#"error: %#",err);
}
return NO;
}

NSXML XML Parsing issue iOS

I know that there are plenty of questions that have been asked and answered and non of them pertain to my problem.
I am posting XML to a server and I get a response back. My problem is getting a specified key back from the response.
I am trying to list all Genders e.g Male, Female and their id's however when parsing the XML into text with NSXML I only get back the Female and ID 2 and I do not get back Male?
I have researched and tried to fix this issue but to no avail.
here is my code:
- (void)getGender {
NSString *soapMessage = [NSString stringWithFormat:
#"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
"<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:app=\"http://app.ws.api.bells.wigroup.com/\">"
"<soap:Header/>\n"
"<soap:Body>\n"
"<app:getAllGenders>\n"
"<request>\n"
"<apiCredentials>\n"
"<apiId>IPHONE_APP</apiId>\n"
"<sha1Password>8656cafcd71cbbfe773a0fdb6c422666a80e5b8f</sha1Password>\n"
"</apiCredentials>\n"
"<request>\n"
"</request>\n"
"</request>\n"
"</app:getAllGenders>\n"
"</soap:Body>\n"
"</soap:Envelope>\n"
];
NSLog(#"Message%#",soapMessage);
NSURL *url = [NSURL URLWithString:#"http://qa.wigroup.co:8080/bells/AppWS"];
NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL:url];
NSString *msgLength = [NSString stringWithFormat:#"%d", [soapMessage length]];
[theRequest addValue: #"text/xml; charset=utf-8" forHTTPHeaderField:#"Content-Type"];
//[theRequest addValue: #"http://" forHTTPHeaderField:#"SOAPAction"];
[theRequest addValue: msgLength forHTTPHeaderField:#"Content-Length"];
[theRequest setHTTPMethod:#"POST"];
[theRequest setHTTPBody: [soapMessage dataUsingEncoding:NSUTF8StringEncoding]];
NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
if( theConnection )
{
NSURLResponse *response;
NSError *error;
NSData *urlData = [NSURLConnection sendSynchronousRequest:theRequest returningResponse:&response error:&error];
NSString *str=[[NSString alloc]initWithData:urlData encoding:NSUTF8StringEncoding];
NSLog(#"Login response XML:%#",str);
// create and init NSXMLParser object
XmlArrayParser *parser = [[XmlArrayParser alloc] initWithData:urlData];
parser.rowElementName = #"return";
parser.elementNames = [NSArray arrayWithObjects:#"response", #"responseCode", #"responseDesc", #"gendersList", nil];
parser.attributeNames = [NSArray arrayWithObjects:#"id", #"gender", nil];
if ([parser.rowElementName isEqualToString:#"responseCode"] && _flag)
{
//read the value here
NSLog(#"flagging");
}
// parsing...
BOOL success = [parser parse];
// test the result
if (success)
{
NSMutableArray *loginAuth = [parser items];
// self.textView.text = [NSString stringWithFormat:
// #"This is an array of dictionaries, one dictionary for each user:\n\n%#",
// [users description]];
// NSDictionary *eventLocation = [NSDictionary dictionaryWithObjectsAndKeys:#"response", nil];
NSDictionary *loginResponse = [loginAuth objectAtIndex:0]; // this retrieves the first user
NSString *userResponse = loginResponse[#"gendersList"]; // this retrieves that user's username in Xcode 4.5 and greater
NSString *userRes = [loginResponse objectForKey:#"id"];
NSString *test = [loginAuth description];
NSLog(#"Returned Code loginResponse %#",loginResponse);
NSLog(#"Returned Code userResponse %# %#",userResponse, userRes);
NSLog(#"Returned Code test %#",test);
NSMutableArray *array=[[NSMutableArray alloc]initWithCapacity:10];
for (NSDictionary *defineXMLData in loginAuth) {
NSNumber * responseCode = [defineXMLData objectForKey:#"responseCode"];
NSArray * responseDEsc = [defineXMLData objectForKey:#"responseDesc"];
NSArray * genderList = [defineXMLData objectForKey:#"gendersList"];
// NSArray * gender = [defineJsonData objectForKey:#"gender"];
NSLog(#"Genders%#", genderList);
[array addObject: responseCode];
[array addObject: responseDEsc];
[array addObject: genderList];
//[array addObject: gender];
// [array addObject: vouchersUser];
}
label.numberOfLines = 2000; // for example
label.lineBreakMode = NSLineBreakByClipping;
NSString *output=[array componentsJoinedByString:#","];
label.text = [NSString stringWithFormat:#"XML Result: %# ",output];
[SVProgressHUD dismiss];
// [[[UIAlertView alloc] initWithTitle:nil
// message:[NSString stringWithFormat:#"No errors - user count : %i", [[parser items] count]]
// delegate:nil
// cancelButtonTitle:#"OK"
// otherButtonTitles:nil] show];
}
else
{
NSLog(#"Error parsing document!");
// [[[UIAlertView alloc] initWithTitle:nil
// message:#"Error parsing document!"
// delegate:nil
// cancelButtonTitle:#"OK"
// otherButtonTitles:nil] show];
}
}
else
{
NSLog(#"theConnection is NULL");
}
NSLog(#"test");
}
And the XML I get back from my nslog:
<?xml version="1.0" encoding="UTF-8"?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns2:getAllGendersResponse xmlns:ns2="http://app.ws.api.bells.wigroup.com/">
<return>
<responseCode>-1</responseCode>
<responseDesc>Success</responseDesc>
<response>
<responseCode>-1</responseCode>
<responseDesc>Success</responseDesc>
<gendersList>
<gender>Male</gender>
<id>1</id>
</gendersList>
<gendersList>
<gender>Female</gender>
<id>2</id>
</gendersList>
</response>
Is only parsing:
{
gendersList = Female2;
responseCode = "-1";
responseDesc = Success;
}
You have not correctly pointed the problem. Your code parses the whole document, but you keep only the last items (last genderList, last responseCode, last responseDesc). Initialize an array and in your for loop add each dictionary to that array when parsed.

iOS : Query regarding dynamically created array

I get four parameters from a web service (web service 2 in my flow) - slno, order, flag, name. I don't know how many times these parameters are going to be received. Out of these four paramters, I send 'name' to a label as it contains questions to be asked.
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"some url"]];
NSLog(#"Web service 2 url is = %#", url);
NSString *json = [NSString stringWithContentsOfURL:url encoding:NSASCIIStringEncoding error:&error];
NSLog(#"Json data = %# \n error = %#", json, error);
if(!error)
{
NSData *jsonData = [json dataUsingEncoding:NSASCIIStringEncoding];
NSArray *myJsonArray = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:Nil];
//NSArray *arrayLabel = [[NSArray alloc] initWithObjects:label1, label2, label3, label4, label5, label6, nil];
//NSMutableArray *tempArray = [NSMutableArray arrayWithCapacity:myJsonArray.count];
i = 0;
for(NSDictionary *myJsonDictionary in myJsonArray)
{
//UILabel *label = (UILabel *)[arrayLabel objectAtIndex:i++];
//[label setText:myJsonDictionary[#"Name"]];
NSString *name = myJsonDictionary[#"Name"];
NSLog(#"Question from ws2 is %#", name);
projectIdGobal = myJsonDictionary[#"ProjectID"];
NSLog(#"Project id from ws2 is %#", projectIdGobal);
slno = myJsonDictionary[#"SLNO"];
NSLog(#"slno from ws2 is %#", slno);
NSString *idWS2 = myJsonDictionary[#"ID"];
NSLog(#"id from ws2 is %#", idWS2);
order = myJsonDictionary[#"Order"];
NSLog(#"order from ws2 is %#", order);
flag = myJsonDictionary[#"Flag"];
NSLog(#"flag from ws2 is %#", flag);
[self putLabelsInScrollView:name];
i++;
}
NSLog(#"Number of cycles in for-each = %d", i);
[activity stopAnimating];
}
- (void) putLabelsInScrollView:(NSString *)labelText
{
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(10, yPosition_label, 261, 30)];
[label setFont:[UIFont fontWithName:#"Helvetica Neue" size:12.0f]];
label.numberOfLines = 2;
[label setText:labelText];
[self.scroll addSubview:label];
yPosition_label += 90;
UITextField *text = [[UITextField alloc] initWithFrame:CGRectMake(10, yPosition_text, 261, 30)];
text.borderStyle = UITextBorderStyleRoundedRect;
text.textColor = [UIColor blackColor];
text.font = [UIFont systemFontOfSize:12.0];
text.backgroundColor = [UIColor clearColor];
text.keyboardType = UIKeyboardTypeDefault;
text.delegate = self;
[self.scroll addSubview:text];
yPosition_text += 90;
yPosition_result = yPosition_label + yPosition_text;
[self.scroll setContentSize:CGSizeMake(self.scroll.frame.size.width, yPosition_result)];
[self.view addSubview:self.scroll];
}
Now I created a dynamically created text fields and stored the answers entered by the user in the array as follows.
- (IBAction)save:(id)sender {
NSMutableArray *mutableTextArray = [[NSMutableArray alloc] init];
for(UITextField *field in self.scroll.subviews)
{
if([field isKindOfClass:[UITextField class]])
{
if([[field text] length] > 0)
{
[mutableTextArray addObject:field.text];
//NSLog(#"Save button 1 : %#", mutableTextArray);
//NSString *str = [str stringByAppendingString:[mutableTextArray objectAtIndex:0]];
//[self fetchStrings:mutableTextArray];
}
}
}
NSLog(#"Save button 2 : %#", mutableTextArray);
[self fetchStrings:mutableTextArray];
}
Now while posting the answer to another web service (web service 3 in my flow), I must pass slno, order, flag i get from web service 2 and the 'answer' that the user enters in the dynamically created field to the 'answer' key. How shall I get these 4 parameters [slno, order, flag (from web service 2) and answer (from dynamic text field)] to post to web service 3?
- (void) fetchStrings:(NSArray *)textArray
{
NSLog(#"Array string = %#", textArray); //I get the array that the user enters in the dynamically created text field here
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
NSUserDefaults *getDefaults = [NSUserDefaults standardUserDefaults];
NSString *uidObject = [getDefaults objectForKey:#"UIDKEY"];
NSString *str = [NSString stringWithFormat:#"{\"ProjID\": \"%#\",\"Uid\": \"%#\",\"EmailID\": \"%#\",", projectIdGobal, uidObject, emailFromLogin];
str = [str stringByAppendingString:#"\"ProjectInviterFQAnswers\": ["];
**for (SaveAsking *saveAsk in textArray) {
str = [str stringByAppendingString:[NSString stringWithFormat:#"{\"slno\":\"%#\",\"Answer\": \"%#\",\"order\": \"%#\", \"flag\": \"%#\"},", saveAsk.slno, saveAsk.answer, saveAsk.order, saveAsk.flag]]; // I want to save the parameters here
}**
// SaveAsking is a nsobject class where I have used a self created delegate for slno answer order and flag
str = [str stringByAppendingString:#"]}"];
NSLog(#"String is === %#", str);
NSURL *url = [NSURL URLWithString:#"some url"];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
NSData *requestData = [str dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPMethod:#"POST"];
[request setValue:#"application/json" forHTTPHeaderField:#"Accept"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[request setValue:[NSString stringWithFormat:#"%d", [requestData length]] forHTTPHeaderField:#"Content-Length"];
[request setHTTPBody: requestData];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[connection start];
[NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error){
if(error || !data)
{
NSLog(#"JSON Data not posted!");
[activity stopAnimating];
UIAlertView *alertMessage = [[UIAlertView alloc] initWithTitle:#"Error" message:#"Data not saved" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertMessage show];
}
else
{
[activity startAnimating];
NSLog(#"JSON data posted! :)");
NSError *error = Nil;
NSJSONSerialization *jsonObject = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&error];
NSLog(#"Response is %#", jsonObject);
}
}];
}
Please do correct my flow if you understood what am i trying to achieve. Number for iterations in left box == number of iterations in right box and the result is in the middle box which needs to be posted to web service.
Try keeping a dictionary of the requests, where the key would be the dynamically created UITextField, and the value would be another dictionary with the values that you need to send.
So , when you create the textField, after adding it to the subview, create a dictionary with your values (sino, order, flag), and set that dictionary to the textfield.
When you are ready to send the data, you'll have a direct connection between the textField and the values for your webservice3.

iOS Check for Token

I'm making an app that requires you to login in. I"m using JSON. So far I've been able send a POST request with the Username and Password and I get a token back (it shows up in the console). When I don't enter in the correct username/password combination, I don't get a token back. What I would like to happen is to proceed to the next view controller if I get a token back. I think that I need to use an if statement (I'll put the code for switching view controllers into it) but I don't know what parameters I need in order to check if I get a token back.
Here is the code I'm using in the implementation file. It is in a method that runs when a button is pressed:
#try {
if([[usernameTextField text] isEqualToString:#""] || [[passTextField text] isEqualToString:#""] ) {
[self alertStatus:#"Please enter both Username and Password" :#"Login Failed!"];
} else {
NSString *post =[[NSString alloc] initWithFormat:#"username=%#&password=%#",[usernameTextField text],[passTextField text]];
NSLog(#"PostData: %#",post);
NSURL *url=[NSURL URLWithString:#"https://beta.network360.com/tokens"];
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *postLength = [NSString stringWithFormat:#"%d", [postData length]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:url];
[request setHTTPMethod:#"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/json" forHTTPHeaderField:#"Accept"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:postData];
NSError *error = [[NSError alloc] init];
NSHTTPURLResponse *response = nil;
NSData *urlData=[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSLog(#"Response code: %d", [response statusCode]);
if ([response statusCode] >=200 && [response statusCode] <300)
{
NSString *responseData = [[NSString alloc]initWithData:urlData encoding:NSUTF8StringEncoding];
NSLog(#"Response ==> %#", responseData);
SBJsonParser *jsonParser = [SBJsonParser new];
NSDictionary *jsonData = (NSDictionary *) [jsonParser objectWithString:responseData error:nil];
NSLog(#"%#",jsonData);
NSInteger success = [(NSNumber *) [jsonData objectForKey:#"success"] integerValue];
NSLog(#"%d",success);
if(success == 1)
{
NSLog(#"Login SUCCESS");
[self alertStatus:#"Logged in Successfully." :#""];
} else {
NSString *error_msg = (NSString *) [jsonData objectForKey:#"error_message"];
[self alertStatus:error_msg :#"Login Failed!"];
}
} else {
if (error) NSLog(#"Error: %#", error);
[self alertStatus:#"Connection Failed" :#""];
}
}
}
#catch (NSException * e)
{
NSLog(#"Exception: %#", e);
[self alertStatus:#"Login Failed." :#""];
//[[PSearchViewController new] performSegueWithIdentifier:#"loginCancel" sender:self];
}
Also, here is what I get in the console output when I put in the correct username/password combination (BTW I tried to change all the stuff that showed up in the console that was confidential, so if some stuff doesn't quite match, it should be fine. I just wanted to show that I get a token back):
2013-07-28 13:23:21.607 Empyrean[28283:c07] PostData: username=username#gmail.com&password=password
2013-07-28 13:23:22.300 Empyrean[28283:c07] Response code: 200
2013-07-28 13:23:22.301 Empyrean[28283:c07] Response ==> {"token":"scFDzxSAVk2sxQBShEGS","user":{"id":300230,"username":"username#gmail.com","display_name":"FirstName LastName","unconfirmed_email":null,"email":"username#gmail.com","confirmation_email":"username#gmail.com","client_identifier":null,"client_id":138,"is_admin":false,"support_email":"support#supportemail.com","application_name":"AppName","show_project_vintage_date":false,"is_anonymous":false,"is_active":true,"is_confirmed":true,"pending_reconfirmation":false,"can_resend_confirmation":false,"client_name":"Broker","show_advertisements":true,"header_logo":"/foo/headerlogo.gif","report_footer_logo":"/stuff/foo/footerlogo.png","authorized_features":["find_stuff","do_stuff","stuff_stuff","settings","menu","manage_stuff","measure_stuff","export_stuff"],"url":"https://www.website.com/stuff/numbersdsjkflds"}}
2013-07-28 13:23:22.304 Empyrean[28283:c07] {
token = dlsfkasdfDfdsklfdDsa;
user = {
"application_name" = "Application Name";
"authorized_features" = (
"find_stuff",
"do_stuff",
"stuff_stuff",
settings,
menu,
"manage_stuff",
"measure_stuff",
"export_stuff"
);
"can_resend_confirmation" = 0;
"client_id" = 138;
"client_identifier" = "<null>";
"client_name" = Broker;
"confirmation_email" = "username#gmail.com";
"display_name" = "FirstName LastName";
email = "username#gmail.com";
"url" = "https://www.website.com/stuff/numbersdsjkflds";
"header_logo" = "/foo/headerlogo.gif";
id = 300230;
"is_active" = 1;
"is_admin" = 0;
"is_anonymous" = 0;
"is_confirmed" = 1;
"pending_reconfirmation" = 0;
"report_footer_logo" = "/stuff/foo/footerlogo.png";
"show_advertisements" = 1;
"show_project_vintage_date" = 0;
"support_email" = "support#supportemail.com";
"unconfirmed_email" = "<null>";
username = "username#gmail.com";
};
}
NSDictionary *jsonData is a dictionary. Therefore, you can see if the token key exists.
if (jsonData[#"token"])
{
// Token exists, so move on.
[self.navigationController pushViewController:nextController animated:YES];
}
else
{
// Tell the user they messed it up.
}

Resources