Objective C setting labels after api call - ios

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.

Related

GCD in iOS not updating my label

I am trying to update my custom label using GCD however all I am getting is the text I initialized the label with:
-(void)drawCardInfo{
__block NSString *cardString;
PPLinearLayoutLabelItem *cardDetails = [[PPLinearLayoutLabelItem alloc] initWithText:#"CREDIT CARD INFO" font:[PPFonts regular18] maxWidth:[LayoutValues getMaxWidthClipped]];
[cardDetails setPaddingTop:20];
[cardDetails setPaddingBottom:10];
[self.topContainerContent addObject:cardDetails];
PPLinearLayoutLabelItem *cardInfo = [[PPLinearLayoutLabelItem alloc] initWithText:#"Data" font:[PPFonts bold16] maxWidth:[LayoutValues getMaxWidthClipped]];
[cardInfo setPaddingTop:0];
[self.topContainerContent addObject:cardInfo];
LinearLayoutHorizontalLine *line1 = [[LinearLayoutHorizontalLine alloc] initWithMaxWidth:[LayoutValues getMaxWidthClipped]];
[self.topContainerContent addObject:line1];
dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSOperationQueue *networkQueue = [[NSOperationQueue alloc] init];
networkQueue.maxConcurrentOperationCount = 5;
NSURL *url = [NSURL URLWithString:#"https://xxxxxxxxxxxxxxxxxx"];
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];
NSString *cardType = [dict objectForKey:#"credit_card_type"];
NSString *cardFinalFour = [dict objectForKey:#"credit_card_last_4"];
cardString = [NSString stringWithFormat:#"%# **** %#",cardType, cardFinalFour];
NSLog(#"%#",cardString);
}
dispatch_async(dispatch_get_main_queue(), ^{ [cardInfo setText:cardString]; });
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"%s: AFHTTPRequestOperation error: %#", __FUNCTION__, error);
}];
[networkQueue addOperation:operation];
});
}
I am successfully logging out the value proving that the network call works fine on a separate thread. Still my label is not being updated. How can I mitigate this?
Looks like you are trying to update the text for the label in a background thread. Updating UI elements on anywhere other than the main thread is not such a good idea since you never know when a asynchronous job will finish.
You can use the following ways to go about it:
Get the main thread and then update the text label
dispatch_async(dispatch_get_main_queue(), ^{
//Code here to which needs to update the UI in the UI thread goes here
});
Use dispatch_sync
Use NSOperations with dependancies (This will be the longest)

Utilizing AFNetworking with YouTube UITableView

I'm hoping someone can help. I am able to list YouTube videos in a tableView without AFNetworking. The code looks something like this:
NSURL *url = [[NSURL alloc] initWithString:#"http://gdata.youtube.com/feeds/api/playlists/PLgw1uRYia2CRrFJW7WT4sKoQxvl_pD0c1?v=2&alt=json&max-results=50&key=AIzaSyA8cyh2w-oa5Z5Wzq6em-ir8YCVF8j1zw4&orderby=published"];
NSData *data = [[NSData alloc] initWithContentsOfURL:url];
NSString *jsonString = [[NSString alloc] initWithData: data encoding:NSUTF8StringEncoding];
NSData *jsonData = [jsonString dataUsingEncoding:NSUnicodeStringEncoding];
NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:jsonData options: NSJSONReadingAllowFragments error:nil];
NSDictionary *feed = [[NSDictionary alloc] initWithDictionary:[jsonDict valueForKey:#"feed"]];
videoArray = [NSMutableArray arrayWithArray:[feed valueForKey:#"entry"]];
[self.videolist reloadData];
The images have to load so scrolling is really weird. Therefore, I would like to utilize AFNetworking. Here's the code I have tried:
AFHTTPRequestOperation *op = [[AFHTTPRequestOperation alloc] initWithRequest:request];
op.responseSerializer = [AFJSONResponseSerializer serializer];
[op setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSDictionary *feed = [[NSDictionary alloc] initWithDictionary:[responseObject valueForKey:#"feed"]];
videoArray = [NSMutableArray arrayWithArray:[feed valueForKey:#"entry"]];
NSLog(#"radio==%#",videoArray);
[self.videolist reloadData];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
And over cellForRowAtIndexPath, it looks something like this:
NSDictionary *video = videoArray[indexPath.row];
NSString *title = [video valueForKeyPath:#"title.$t"];
cell.videotitle.text = title;
That doesn't work for some reason, even when there are no errors. Help?
The videolist wasn't linked to the table in the Storyboard. The issue is now resolved.

Objective C, update table view after async operation

I am running an async operation which loops through a json data file which should then update a table view.
Here's the code i'm using.
-(void) TopDealsRecieve:(NSString *)Devicetoken;
{
currentcount = 0;
allcontent = newArray;
//Send device token and retireve TopDeals
NSString *mainURL = #"http://myurl.com/api/";
NSString *firstprefix = #"type=apicall&device=";
NSString *deviceIDforURL = [NSString stringWithFormat:#"%#", Devicetoken];
NSString *stringToGoToEncoder = [NSString stringWithFormat: #"%#%#", firstprefix, deviceIDforURL];
NSData *plainData = [stringToGoToEncoder dataUsingEncoding:NSUTF8StringEncoding];
NSString *base64String = [plainData base64EncodedStringWithOptions:0];
NSString *returnURL = [NSString stringWithFormat:#"%#%#", mainURL, base64String];
NSURL *returncompletedURL = [[NSURL alloc] initWithString:returnURL];
//Retrieve Dictionary of Top Deals
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:returncompletedURL];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
operation.responseSerializer = [AFJSONResponseSerializer serializer];
operation.responseSerializer.acceptableContentTypes = [NSSet setWithObject:#"text/html"];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
//Get all output and store for segue
NSLog(#"%#", responseObject);
currentcount++;
numrows = [responseObject valueForKey:#"rows"];
numrowscompare = [numrows integerValue];
allLogos = [[responseObject valueForKey:#"data"] valueForKey:#"logo"];
allcontent = [[responseObject valueForKey:#"data"] valueForKey:#"content"];
allpostode = [[responseObject valueForKey:#"data"] valueForKey:#"postcode"];
NSLog(#"%lu", (unsigned long)allcontent.count);
allname = [[responseObject valueForKey:#"data"] valueForKey:#"name"];
alladdress = [[responseObject valueForKey:#"data"] valueForKey:#"address"];
alladdress2 = [[responseObject valueForKey:#"data"] valueForKey:#"address2"];
alllat = [[responseObject valueForKey:#"data"] valueForKey:#"lat"];
alllong = [[responseObject valueForKey:#"data"] valueForKey:#"lng"];
allstart = [[responseObject valueForKey:#"data"] valueForKey:#"start"];
allfinish = [[responseObject valueForKey:#"data"] valueForKey:#"finish"];
allstartnice = [[responseObject valueForKey:#"data"] valueForKey:#"nicestart"];
allfinishnice = [[responseObject valueForKey:#"data"] valueForKey:#"nicefinish"];
// hide the ticker
[self.tableview reloadData];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
// 4
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Error Retrieving Top Deals check internet connection!"
message:[error localizedDescription]
delegate:nil
cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
[alertView show];
}];
[operation start];
}
When running the operation all the data comes in fine to the console, however the table view does not update with the correct data. It updates with the data in the all content array from before calling the function.
It seems that the data from the server isn't being passed to the table view quick enough. I somehow need to get the table view to reloadData AFTER the operation has been completed in some sort of queue.
[self.tableview reloadData];
Sorry if not too clear, any help appreciated.
If allContent is the NSArray your UITableViewDatasource uses, then you never update it in your completionBlockWithSuccess, so this isn't a problem of async update but rather a simple mistake : update allContent just before calling reloadData.
(One additionnal remark : using 'Global' arrays is bad!)

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.

how to send array as a parameter in Afnetwoking post method?

hi i need to send a array as a one of the parameter in Afnetworking Query String
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:#"http://192.008.0.28/aaa/a/"]];
NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys: #"20", #"Miles", [NSArray arrayWithObjects:#"1",#"2",#"3",nil], #"Interval", nil];
[httpClient postPath:iUpdateNotificationMethod parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSString *responseStr = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
NSLog(#"Request Successful, response '%#'", responseStr);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"[HTTPClient Error]: %#", error.localizedDescription);
}];
But server side we got "Miles":20,"Intervals":null how to fix it
Thanks,
Try This
AFHTTPClient *client = [[AFHTTPClient alloc] initWithBaseURL:OAuthBaseURL];
NSMutableDictionary *parameters = [[NSMutableDictionary alloc] initWithCapacity:0];
for (int i =0; i < [userIDs count]; i++) {
NSString *userID = [[userIDs objectAtIndex:i] objectForKey:#"id"];
NSDictionary *tmpDict = [NSDictionary dictionaryWithObjectsAndKeys:userID , [NSString stringWithFormat:#"ids[%i]",i], nil];
[parameters addEntriesFromDictionary:tmpDict];
}
[client postPath:#"/user"
parameters:parameters
success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSData *data = (NSData *)responseObject;
NSString *jsonStr = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(#"jsonStr %#",jsonStr);
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
[self showError];
}
];
Since you're submitting an array, AFNetworking is generating a different parameter name and overloads it with the values you supply. For example, your request generates the following querystring:
Interval[]=1&Interval[]=2&Interval[]=3&Miles=20
This is defined in AFHTTPClient.m in the AFQueryStringPairsFromKeyAndValue function.
If you want to keep the original parameter, you should decide how to convert your NSArray to NSString by yourself. For example, you can do something like [myArray componentsJoinedByString:#","] and then split it back to elements on the server. If you choose this method, beware of using characters that might appear in your actual data.
I believe this will work:
params = #{ #"Miles": #"20", #"Interval": #[#"1",#"2",#"3"] };

Resources