How to pass data to the View Controller using asynchronous NSURLConnection - ios

I have View Controller where I get data from web, parse Json, and pass string to another View Controller. If I use synchronous NSURLConnection, everything works just fine.
But if I switch to the asynchronous, then method (void)prepareForSegue:(UIStoryboardSegue *) calls before parsing Json data which I got from web.
Just jump over _jsonArray = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil] method. Any thoughts? Thank you in advance for your help. Here is my code:
-(void)getClothInfo {
NSString *allowedClothSizeToServer = [_foreignSizeToServer stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
NSString *getDataURL = [NSString stringWithFormat:#"http://xsdcompany.com/jsoncloth.php?foreignSize=%#",allowedClothSizeToServer];
NSURL *url = [NSURL URLWithString:getDataURL];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"GET"];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler: ^(NSURLResponse *response, NSData *data, NSError *connectionError) {
if (connectionError) {
[self showAlertWithMessage2:#"Server is Unavialable"];
} else {
_jsonArray = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
//Loop trough our jsonArray
for (int i=0; i<_jsonArray.count; i++) {
//Create our size object
_usSizeFromServer = [[_jsonArray objectAtIndex:i] objectForKey:#"usSizeCloth"];
}
}
}];
}
- (IBAction)getIt:(id)sender {
// Validate data
if ([self validData] == NO)
{
return;
}
[self getClothInfo];
[self showNextViewController];
}
-(void) showNextViewController {
[self performSegueWithIdentifier:#"GetCLothInfo" sender:nil];
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
ResultViewController *resultViewController = [segue destinationViewController];
resultViewController.foreignSizeToResult = [[NSString alloc] initWithFormat:#"%# size for %# is %#", [_pickerProcessor selectedCountry].countryName, [_pickerProcessor selectedCloth].clothName, [_pickerProcessor selectedSize].sizeName];
resultViewController.dataForUsSize = [[NSString alloc] initWithFormat:#"Your US size for %# is %#", [_pickerProcessor selectedCloth].clothName, _usSizeFromServer];
}

You have two options. You could call showNextViewController from the completion block inside the getClothInfo method. Or better, add a completion block parameter to your getClothInfo method and call that from the completion block for the NSURLConnection.
Something like this:
-(void)getClothInfo:(void ^(void))completion {
NSString *allowedClothSizeToServer = [_foreignSizeToServer stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
NSString *getDataURL = [NSString stringWithFormat:#"http://xsdcompany.com/jsoncloth.php?foreignSize=%#",allowedClothSizeToServer];
NSURL *url = [NSURL URLWithString:getDataURL];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"GET"];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler: ^(NSURLResponse *response, NSData *data, NSError *connectionError) {
if (connectionError) {
[self showAlertWithMessage2:#"Server is Unavialable"];
} else {
_jsonArray = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
//Loop trough our jsonArray
for (int i=0; i<_jsonArray.count; i++) {
//Create our size object
_usSizeFromServer = [[_jsonArray objectAtIndex:i] objectForKey:#"usSizeCloth"];
}
if (completion) {
dispatch_async(dispatch_get_main_queue(), ^{
completion();
});
}
}
}];
}
- (IBAction)getIt:(id)sender {
// Validate data
if ([self validData] == NO)
{
return;
}
[self getClothInfo:^ {
[self showNextViewController];
}];
}

It seems like you want your json data to be downloaded before you segue, in that case the synchronous NSURLConnection makes sense
When you make an asynchronous NSURLConnection call, it means that the subsequent code will be executed ( in this case the performSegue).
It would help if you could explain what your expected behavior is

Register for notification when response is obtained from the connection using
[[NSNotificationCenter defaultCenter] postNotificationName:#"ResponseObtained" object:_jsonArray];
in the second view controller add observer for notification
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(handleResponse:)
name:#"ResponseObtained"
object:nil];
You can access _jasonArray in handleResponse method with
- (void)handleResponse:(NSNotification *)notif{
NSDictionary *result = [notif object]; }

Related

PrepareForSegue called before didSelectRowAtIndexPath

I am calling the following method in didSelectRowAtIndexPath.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath: (NSIndexPath *)indexPath{
[self unreadMessageCounter];
}
In that method I am getting a value with parameter name "MsgCount". For that the written code is.
-(void) unreadMessageCounter{
NSUserDefaults *defaultUser=[NSUserDefaults standardUserDefaults];
NSString* username = [defaultUser objectForKey:KUserName];
NSString* password = [defaultUser objectForKey:KPassword];
dispatch_async(dispatch_get_main_queue(), ^{
[SVProgressHUD showWithStatus:#"Loading..." maskType:SVProgressHUDMaskTypeGradient];
});
NSString *url3 ;
NSString *base_url=[[NSUserDefaults standardUserDefaults] objectForKey:#"BASE_URL"];
url3=[[NSString alloc]initWithFormat:#"%#%#? username=%#&password=%#&deviceUniqueId=%#",base_url,MESSAGE_COUNTER,username,password,[defaultUser objectForKey:KDeviceToken]];
[defaultUser synchronize];
NSURL *requestURL = [NSURL URLWithString:[url3 stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:requestURL];
[request setHTTPMethod:#"GET"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *urlResponse, NSError *error) {
NSHTTPURLResponse *response = (NSHTTPURLResponse *)urlResponse;
NSLog(#"Response Code For Message Counter:: %ld", (long)[response statusCode]);
if(response){
NSMutableDictionary *returneDict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
NSLog(#"Return Dict For Message Counter:: %#", returneDict);
if (returneDict != nil) {
if ([returneDict valueForKey:#"valueSet"]){
for (NSDictionary *dict in [returneDict valueForKey:#"valueList"]) {
_counterNumber = dict[#"MsgCount"];
NSLog(#"counter number %#", _counterNumber);
}
}
else{
dispatch_async(dispatch_get_main_queue(), ^{
[SVProgressHUD dismiss];
});
}
}
else{
dispatch_async(dispatch_get_main_queue(), ^{
[SVProgressHUD dismiss];
});
}
}
}];
[task resume];
}
After that I am passing that _counterNumber string to the next view controller with the help of prepareForSegue, for that the following code is.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if (![segue.identifier isEqualToString:#"Show Notification"]) {
UINavigationController *nav = [segue destinationViewController];
WelcomeScreenViewController *welcomeScreenViewController = (WelcomeScreenViewController *)nav.topViewController;
welcomeScreenViewController.counterString = _counterNumber;
}
}
It was going to the next view controller but on the first call, after didselectrowatindexpath instead of unreadMessageCounter method, prepareForSegue is getting call that's why the _counterNumber value I am getting nil, but on the second time when I am calling then It is working as usual. So plese help me in that case because I am not getting any clue.
First Disconnect your segue from cell to nextViewController. And make new segue from current ViewController to your nextViewController like below screenshot
And after processing you API that you are calling in didSelectRowAtIndexPath perform segue through code like below.
[self performSegueWithIdentifier: #"Show Notification" sender: self];

iOS: Unrecognized selector sent to instance

I have a class where I request information from a provider class, in which after finalizing the job (asynchronous httpRequest block) needs to invoke a method [- (void) updateCountries] in the requester class. If I am not wrong this code worked in iOS 7, but now in iOS 8 it does not.
Can you please help me to understand why?
Methods in requester class:
- (void) viewWillAppear:(BOOL)animated {
//get countries to pickerView
webAPI = [[WebAPI alloc] init];
[webAPI retrieveCountries:self];
}
- (void) updateCountries {
//update countries content for pickerView
locationDAO = [[LocationDAO alloc] init];
countriesArray = [locationDAO getCountries];
[pickerView reloadAllComponents];
}
Lines in method in provider class where error happens:
SEL updateCountries = sel_registerName("updateCountries:");
[requester performSelectorOnMainThread:updateCountries withObject:nil waitUntilDone:YES];
If you need to checkout the entire method in the provider class, here it is:
- (void) retrieveCountries:(id)requester {
// NSLog(#"engine report: firing retrieveCountries http get");
NSString *urlAsString = kRetrieveCountriesListAPI;
NSURL *url = [NSURL URLWithString:urlAsString];
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url];
[urlRequest setTimeoutInterval:30.0f];
[urlRequest setHTTPMethod:#"GET"];
[urlRequest setValue:#"application/json" forHTTPHeaderField:#"Content-type"];
[NSURLConnection sendAsynchronousRequest:urlRequest queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if ([data length] >0 && error == nil){
NSString *response = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"engine report: retrieveCountries server response: %#", response);
NSArray *level0 = [[NSArray alloc] initWithObjects:[NSJSONSerialization JSONObjectWithData:[[NSData alloc] initWithData:data] options:kNilOptions error:&error], nil];
NSArray *level1 = [level0 objectAtIndex:0];
LocationDAO *locationDAO = [[LocationDAO alloc] init];
[locationDAO deleteAllFromCountries];
for (int i = 0; i < [level1 count]; i++) {
CountryVO *countryVO = [[CountryVO alloc] init];
countryVO.myID = [[[level1 objectAtIndex:i] objectForKey:#"id"] integerValue];
countryVO.name = [[level1 objectAtIndex:i] objectForKey:#"country_name"];
[locationDAO saveCountryToDatabase:countryVO];
}
SEL updateCountries = sel_registerName("updateCountries:");
[requester performSelectorOnMainThread:updateCountries withObject:nil waitUntilDone:YES];
dispatch_async(dispatch_get_main_queue(), ^(void){
});
} else if ([data length] == 0 && error == nil){
NSLog(#"Nothing was downloaded.");
} else if (error != nil) {
NSLog(#"Error happened = %#", error);
} }];
}
THANK YOU A WHOLE LOT
Remove the : from the selector specification:
SEL updateCountries = sel_registerName("updateCountries");
Your method updateCountries doesn't take any arguments. So, when creating the selector, you should only write updateCountries (instead of updateCountries: which would indicate that this method takes an argument).
The reason why your app crashes is that when you try to perform this selector, the internals of your app are looking for a method called updateCountries on requester that takes one argument. This method doesn't exist, which is why the app crashes.

NSURLConnection wrong order

I have a NSURLConnection (two of them), and they're running in the wrong order.
Here's my method:
- (void)loginToMistarWithPin:(NSString *)pin password:(NSString *)password {
NSURL *url = [NSURL URLWithString:#"https://mistar.oakland.k12.mi.us/novi/StudentPortal/Home/Login"];
//Create and send request
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
[request setHTTPMethod:#"POST"];
NSString *postString = [NSString stringWithFormat:#"Pin=%#&Password=%#",
[self percentEscapeString:pin],
[self percentEscapeString:password]];
NSData * postBody = [postString dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPBody:postBody];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
{
// do whatever with the data...and errors
if ([data length] > 0 && error == nil) {
NSError *parseError;
NSDictionary *responseJSON = [NSJSONSerialization JSONObjectWithData:data options:0 error:&parseError];
if (responseJSON) {
// the response was JSON and we successfully decoded it
NSLog(#"Response was = %#", responseJSON);
} else {
// the response was not JSON, so let's see what it was so we can diagnose the issue
NSString *loggedInPage = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"Response was not JSON (from login), it was = %#", loggedInPage);
}
}
else {
NSLog(#"error: %#", error);
}
}];
//Now redirect to assignments page
NSURL *homeURL = [NSURL URLWithString:#"https://mistar.oakland.k12.mi.us/novi/StudentPortal/Home/PortalMainPage"];
NSMutableURLRequest *requestHome = [[NSMutableURLRequest alloc] initWithURL:homeURL];
[request setHTTPMethod:#"POST"];
[NSURLConnection sendAsynchronousRequest:requestHome queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *homeResponse, NSData *homeData, NSError *homeError)
{
// do whatever with the data...and errors
if ([homeData length] > 0 && homeError == nil) {
NSError *parseError;
NSDictionary *responseJSON = [NSJSONSerialization JSONObjectWithData:homeData options:0 error:&parseError];
if (responseJSON) {
// the response was JSON and we successfully decoded it
NSLog(#"Response was = %#", responseJSON);
} else {
// the response was not JSON, so let's see what it was so we can diagnose the issue
NSString *homePage = [[NSString alloc] initWithData:homeData encoding:NSUTF8StringEncoding];
NSLog(#"Response was not JSON (from home), it was = %#", homePage);
}
}
else {
NSLog(#"error: %#", homeError);
}
}];
}
- (NSString *)percentEscapeString:(NSString *)string
{
NSString *result = CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
(CFStringRef)string,
(CFStringRef)#" ",
(CFStringRef)#":/?#!$&'()*+,;=",
kCFStringEncodingUTF8));
return [result stringByReplacingOccurrencesOfString:#" " withString:#"+"];
}
So, it's two NSURLConnection's that are added to the [NSOperationQueue mainQueue]. What my output is showing me is that the second NSURLConnection is running before the first one. So it tries to go to the page where I download data before I'm logged in, so it (obviously) returns a "You're not logged in" error.
How do I schedule them one after another?
The issue, as I suspect you have realized, is that you're doing asynchronous network requests (which is good; you don't want to block the main queue), so there's no assurance of the order they'll finish.
The quickest and easiest answer is to simply put the call to the second request inside the completion block of the first one, not after it. You don't want to be making that second one unless the first one succeeded anyway.
To keep your code from getting unwieldy, separate the login from the request for main page. And you can use the completion block pattern which is common with asynchronous methods. You add a parameter to loginToMistarWithPin that specifies what it should do when the request finishes. You might have one completion block handler for success, and one for failure:
- (void)loginToMistarWithPin:(NSString *)pin password:(NSString *)password success:(void (^)(void))successHandler failure:(void (^)(void))failureHandler {
NSURL *url = [NSURL URLWithString:#"https://mistar.oakland.k12.mi.us/novi/StudentPortal/Home/Login"];
//Create and send request
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
[request setHTTPMethod:#"POST"];
NSString *postString = [NSString stringWithFormat:#"Pin=%#&Password=%#",
[self percentEscapeString:pin],
[self percentEscapeString:password]];
NSData * postBody = [postString dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPBody:postBody];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
{
// do whatever with the data...and errors
if ([data length] > 0 && error == nil) {
NSError *parseError;
NSDictionary *responseJSON = [NSJSONSerialization JSONObjectWithData:data options:0 error:&parseError];
if (responseJSON) {
// the response was JSON and we successfully decoded it
NSLog(#"Response was = %#", responseJSON);
// assuming you validated that everything was successful, call the success block
if (successHandler)
successHandler();
} else {
// the response was not JSON, so let's see what it was so we can diagnose the issue
NSString *loggedInPage = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"Response was not JSON (from login), it was = %#", loggedInPage);
if (failureHandler)
failureHandler();
}
}
else {
NSLog(#"error: %#", error);
if (failureHandler)
failureHandler();
}
}];
}
- (void)requestMainPage {
//Now redirect to assignments page
NSURL *homeURL = [NSURL URLWithString:#"https://mistar.oakland.k12.mi.us/novi/StudentPortal/Home/PortalMainPage"];
NSMutableURLRequest *requestHome = [[NSMutableURLRequest alloc] initWithURL:homeURL];
[requestHome setHTTPMethod:#"GET"]; // this looks like GET request, not POST
[NSURLConnection sendAsynchronousRequest:requestHome queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *homeResponse, NSData *homeData, NSError *homeError)
{
// do whatever with the data...and errors
if ([homeData length] > 0 && homeError == nil) {
NSError *parseError;
NSDictionary *responseJSON = [NSJSONSerialization JSONObjectWithData:homeData options:0 error:&parseError];
if (responseJSON) {
// the response was JSON and we successfully decoded it
NSLog(#"Response was = %#", responseJSON);
} else {
// the response was not JSON, so let's see what it was so we can diagnose the issue
NSString *homePage = [[NSString alloc] initWithData:homeData encoding:NSUTF8StringEncoding];
NSLog(#"Response was not JSON (from home), it was = %#", homePage);
}
}
else {
NSLog(#"error: %#", homeError);
}
}];
}
Then, when you want to login, you can do something like:
[self loginToMistarWithPin:#"1234" password:#"pass" success:^{
[self requestMainPage];
} failure:^{
NSLog(#"login failed");
}];
Now, change those successHandler and failureHandler block parameters to include whatever data you need to pass back, but hopefully it illustrates the idea. Keep your methods short and tight, and use completion block parameters to specify what an asynchronous method should do when it's done.
Can you check the below link. It is about forcing one operation to wait for another.
NSOperation - Forcing an operation to wait others dynamically
Hope this helps.

NSURLConnection delegate methods

I am using a button action to update the value of a MySQL table field. The update is perform in the web server, but I need to update a UILabel text in my view Controller.
This is the code I have implemented:
- (IBAction)votarAction:(id)sender {
//URL definition where php file is hosted
dispatch_queue_t backgroundQueue = dispatch_queue_create("com.mycompany.myqueue", 0);
dispatch_async(backgroundQueue, ^{
int categoriaID = [[detalleDescription objectForKey:#"idEmpresa"] intValue];
NSString *string = [NSString stringWithFormat:#"%d", categoriaID];
NSLog(#"ID EMPRESA %#",string);
NSMutableString *ms = [[NSMutableString alloc] initWithString:#"http://mujercanariasigloxxi.appgestion.eu/app_php_files/cambiarvaloracionempresa.php?id="];
[ms appendString:string];
// URL request
NSLog(#"URL = %#",ms);
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:ms]];
//URL connection to the internet
NSURLConnection *connection=[[NSURLConnection alloc]initWithRequest:request delegate:self];
dispatch_async(dispatch_get_main_queue(), ^{
//update your label
});
});
}
#pragma NSURLConnection Delegate Methods
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
//buffer is the object Of NSMutableData and it is global,so declare it in .h file
buffer = [NSMutableData data];
NSLog(#"ESTOY EN didReceiveResponse*********");
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
NSLog(#"ESTOY EN didReceiveDATA*********");
[buffer appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
//Here You will get the whole data
NSLog(#"ESTOY EN didFINISHLOADING*********");
NSError *jsonParsingError = nil;
NSArray *array = [NSJSONSerialization JSONObjectWithData:buffer options:0 error:&jsonParsingError];
//And you can used this array
NSLog(#"ARRAY = %#",array);
//HERE LABEL.TEXT UPDATE CODE
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(#"ERROR de PARSING");
NSLog(#"ESTOY EN didFAILWITHERROR*********");
}
As I told you, the field value at the MySQL table is updated every time the button is tapped, but the problem is that the NSURLConnection delegate methods are never called.
Any help is welcome
In your view controller's header file add: <NSURLConnectionDelegate>
Also, there's no need to throw the NSURLConnection into a seperate background process, maybe that's why the delegates aren't called. NSURLConnection is already asynchronous
Perhaps try something like this:
- (IBAction)votarAction:(id)sender
{
int categoriaID = [[detalleDescription objectForKey:#"idEmpresa"] intValue];
NSString *originalString = [NSString stringWithFormat:#"%d", categoriaID];
NSMutableString *mutablesString = [[NSMutableString alloc] initWithString:#"http://mujercanariasigloxxi.appgestion.eu/app_php_files/cambiarvaloracionempresa.php?id="];
[mutableString appendString:originalString];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:mutableString]];
request.cachePolicy = NSURLRequestReloadIgnoringLocalAndRemoteCacheData;
request.timeoutInterval = 5.0;
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:
^(NSURLResponse *response, NSData *data, NSError *connectionError)
{
if (data)
{
NSArray *array = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
dispatch_async(dispatch_get_main_queue(), ^
{
// Update your label
self.label.text = [array objectAtIndex:someIndex];
});
}
else
{
// Tell user there's no internet or data failed
}
}];
}

How to enumerate through NSArray of NSDictionaries with a block call inside the loop?

I get an self.usersArray with 2 elements in the format:
(
{
userCreated = "2012-01-05 12:27:22";
username = Simulator;
},
{
userCreated = "2013-01-01 14:27:22";
username = "joey ";
}
)
This is gotten in a completion block after which I call another method to fetch points for these 2 users through a helper class:
-(void)getPoints{
self.usersPointsArray = [[NSMutableArray alloc] init];
for (NSDictionary *usersDictionary in self.usersArray) {
[SantiappsHelper fetchPointsForUser:[usersDictionary objectForKey:#"username"] WithCompletionHandler:^(NSArray *points){
if ([points count] > 0) {
[self.usersPointsArray addObject:[points objectAtIndex:0]];
}
NSLog(#"self.usersPointsArray %#", self.usersPointsArray);
}];
}
}
The final self.usersPointsArray log looks like:
(
{
PUNTOS = 5;
username = Simulator;
},
{
PUNTOS = 2;
username = joey;
}
)
But the problem is that the way the call for points is structured, the self.usersPointsArray is returned twice, each time with an additional object, due to the for loop, I know.
Here is the Helper class method:
+(void)fetchPointsForUser:(NSString*)usuario WithCompletionHandler:(Handler2)handler{
NSURL *url = [NSURL URLWithString:#"http://myserver.com/myapp/readpoints.php"];
NSDictionary *postDict = [NSDictionary dictionaryWithObjectsAndKeys:usuario, #"userNa", nil];
NSData *postData = [self encodeDictionary:postDict];
// Create the request
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"POST"];
[request setValue:[NSString stringWithFormat:#"%d", postData.length] forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/x-www-form-urlencoded charset=utf-8" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:postData];
__block NSArray *pointsArray = [[NSArray alloc] init];
dispatch_async(dispatch_get_main_queue(), ^{
// Peform the request
NSURLResponse *response;
NSError *error = nil;
NSData *receivedData = [NSURLConnection sendSynchronousRequest:request
returningResponse:&response
error:&error];
if (error) {
if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response;
NSLog(#"HTTP Error: %d %#", httpResponse.statusCode, error);
return;
}
return;
}
NSString *responseString = [[NSString alloc] initWithData:receivedData encoding:NSUTF8StringEncoding];
pointsArray = [NSJSONSerialization JSONObjectWithData:[responseString dataUsingEncoding:NSASCIIStringEncoding] options:0 error:nil];
if (handler)
handler(pointsArray);
});
}
I cannot use the self.usersPointsArray with the initial objects, only with the finalized object. It wont always be 2 elements, i actually dont know how many it will be.
What would be the way to structure it so I get a final call when the self.usersPointsArray is complete and then I reload my tableview?
I think of your problem as a standard consumer-producer problem. You can create a queue count for the amount of items that will be processed (int totalToProcess=self.usersArray.count). Each time the completion handler is hit, it will do totalToProcess--. When totalToProcess reaches 0 you have processed all of the elements in your queue and can refresh your table.
If I understand your question correctly I believe this solves your problem. If not, hopefully I can with a bit more information.

Resources