Activity Indicator while calling API - ios

I want to display the activity indicator while waiting for the API to return. The problem is after all the result I get from API, then the spinner only display. The result I want is while waiting for API call, then the spinner will running.
I'm calling this method in here
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
[self startLoadingSpinner]
//Calling API...
[self stopLoadingSpinner]
}
Here is the method for the activity indicator
-(void)startLoadingSpinner {
self.activityIndicator = [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(0, 0, 70, 70)];
self.activityIndicator.opaque = YES;
self.activityIndicator.backgroundColor = [UIColor colorWithWhite:0.0f alpha:0.4f];
self.activityIndicator.center = self.view.center;
self.activityIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyleGray;
[self.activityIndicator setColor:[UIColor whiteColor]];
[self.view addSubview:self.activityIndicator];
[self.activityIndicator startAnimating];
}
This is how I stop the activity indicator
-(void)stopLoadingSpinner {
[self.activityIndicator performSelector:#selector(removeFromSuperview) withObject:nil afterDelay:0.5];
}

Don't add activity indicators in tableview datasource method - numberOfRowsInSection .
Add these two functions calling in the same method where you are making an API call. Make an API call in ViewDidLoad, some life cycle method or in action methods.
Below is the example of using it.
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
NSURL *URL = [NSURL URLWithString:#"http://httpbin.org/get"];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
[self startLoadingSpinner]
NSURLSessionDataTask *dataTask = [manager dataTaskWithRequest:request completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
if (error) {
NSLog(#"Error: %#", error);
} else {
NSLog(#"%# %#", response, responseObject);
}
[self stopLoadingSpinner]
}];
[dataTask resume];
In Swift
func makeAPIRequest(to endPoint: String) {
// here you can showActivetyIndicator start progressing here
self.startLoadingSpinner()
Alamofire.request(endPoint).responseJSON{ response in
if let value = response.result.value {
let responseInJSON = JSON(value)
self._responseInJSON = responseInJSON
}
// here you can hide Your ActivetyIndicator here
self.stopLoadingSpinner()
}
}

My detailed answer is below
-(void)simpleGetResponse{
#try {
//Call the Activity Indicator show method here
[self startLoadingSpinner];
NSString *strURL = #"Your URL";
NSURL *urlStr = [NSURL URLWithString:strURL];
NSMutableURLRequest *mutaURL = [NSMutableURLRequest requestWithURL:urlStr];
[mutaURL setHTTPMethod:#"GET"];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:mutaURL completionHandler:^(NSData *data, NSURLResponse *response, NSError *error)
{
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
if(httpResponse.statusCode == 200)
{
NSError *parseError = nil;
id response = [NSJSONSerialization JSONObjectWithData:data options:0 error:&parseError];
if(response != nil){
if([response isKindOfClass:[NSDictionary class]]){
NSLog(#"response is in dictionary format %#",response);
NSDictionary *dictRes = [response copy];
NSLog(#"The dictRes is - %#",dictRes);
}
else{
NSLog(#"response is in array format %#",response);
NSDictionary *arrRes = [response copy];
NSLog(#"The arrRes is - %#",arrRes);
}
dispatch_async(dispatch_get_main_queue(), ^{
//Call the Activity Indicator hidden method inside the dispatch_main_queue method
[self stopLoadingSpinner]
[yourTableView reloadData];
});
}
}
else
{
NSLog(#"Error");
}
}];
[dataTask resume];
}
#catch (NSException *exception) {
NSLog(#"%#", [exception description]);
}
#finally {
}
}

Related

Why is background NSURLConnection having error when enter background?

I am having this error when my app enter background.
NSURLConnection finished with error - code -1001 Task
<09B84034-9F73-4DB6-A685-D891B1B1068A>.<2> finished with error - code:
-1001
I am using this code
- (id<XCDYouTubeOperation>) getVideoWithIdentifier:(NSString *)videoIdentifier completionHandler:(void (^)(XCDYouTubeVideo * __nullable video, NSError * __nullable error))completionHandler
{
NSLog(#"Getting Video Identfifier");
if (!completionHandler)
#throw [NSException exceptionWithName:NSInvalidArgumentException reason:#"The `completionHandler` argument must not be nil." userInfo:nil];
XCDYouTubeVideoOperation *operation = [[XCDYouTubeVideoOperation alloc] initWithVideoIdentifier:videoIdentifier languageIdentifier:self.languageIdentifier];
operation.completionBlock = ^{
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-retain-cycles"
if (operation.video || operation.error)
{
NSAssert(!(operation.video && operation.error), #"One of `video` or `error` must be nil.");
completionHandler(operation.video, operation.error);
}
else
{
NSAssert(operation.isCancelled, #"Both `video` and `error` can not be nil if the operation was not canceled.");
}
operation.completionBlock = nil;
#pragma clang diagnostic pop
}];
};
NSLog(#"Operation - %#", operation ) ;
[self.queue addOperation:operation];
return operation;
}`
- (void) startRequestWithURL:(NSURL *)url type:(XCDYouTubeRequestType)requestType
{
if (self.isCancelled)
return;
// Max (age-restricted VEVO) = 2×GetVideoInfo + 1×WatchPage + 1×EmbedPage + 1×JavaScriptPlayer + 1×GetVideoInfo
if (++self.requestCount > 6)
{
// This condition should never happen but the request flow is quite complex so better abort here than go into an infinite loop of requests
[self finishWithError];
return;
}
XCDYouTubeLogDebug(#"Starting request: %#", url);
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10];
[request setValue:self.languageIdentifier forHTTPHeaderField:#"Accept-Language"];
NSLog(#"Request Type - ",requestType);
// NSURLSessionDataTask *task = [self.session dataTaskWithRequest:request];
// [task resume];
self.dataTask = [self.session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error)
{
if (self.isCancelled)
return;
if (error)
[self handleConnectionError:error];
else
[self handleConnectionSuccessWithData:data response:response requestType:requestType];
}];
[self.dataTask resume];
self.requestType = requestType;
}
#pragma mark - Response Dispatch
- (void) handleConnectionSuccessWithData:(NSData *)data response:(NSURLResponse *)response requestType:(XCDYouTubeRequestType)requestType
{
NSLog(#"XCDDRequestType - ",requestType);
CFStringEncoding encoding = CFStringConvertIANACharSetNameToEncoding((__bridge CFStringRef)response.textEncodingName ?: CFSTR(""));
// Use kCFStringEncodingMacRoman as fallback because it defines characters for every byte value and is ASCII compatible. See https://mikeash.com/pyblog/friday-qa-2010-02-19-character-encodings.html
NSString *responseString = CFBridgingRelease(CFStringCreateWithBytes(kCFAllocatorDefault, data.bytes, (CFIndex)data.length, encoding != kCFStringEncodingInvalidId ? encoding : kCFStringEncodingMacRoman, false)) ?: #"";
NSAssert(responseString.length > 0, #"Failed to decode response from %# (response.textEncodingName = %#, data.length = %#)", response.URL, response.textEncodingName, #(data.length));
XCDYouTubeLogVerbose(#"Response: %#\n%#", response, responseString);
switch (requestType)
{
case XCDYouTubeRequestTypeGetVideoInfo:
[self handleVideoInfoResponseWithInfo:XCDDictionaryWithQueryString(responseString) response:response];
break;
case XCDYouTubeRequestTypeWatchPage:
[self handleWebPageWithHTMLString:responseString];
break;
case XCDYouTubeRequestTypeEmbedPage:
[self handleEmbedWebPageWithHTMLString:responseString];
break;
case XCDYouTubeRequestTypeJavaScriptPlayer:
[self handleJavaScriptPlayerWithScript:responseString];
break;
}
}
This code will automatically run in background but after a few minutes it will stop and gives me the above error. How to fix this ?
EDIT 1 (Vinay Kiran Method) #
i changed the nsurlsessionconfiguration to background.
- (instancetype) initWithVideoIdentifier:(NSString *)videoIdentifier languageIdentifier:(NSString *)languageIdentifier
{
if (!(self = [super init]))
return nil; // LCOV_EXCL_LINE
_videoIdentifier = videoIdentifier ?: #"";
_languageIdentifier = languageIdentifier ?: #"en";
// _session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration ephemeralSessionConfiguration]];
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:#"YouTubeID"];
_session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];
_operationStartSemaphore = dispatch_semaphore_create(0);
NSLog(#"Initialize the Video Identifier");
return self;
}
then change the completion handler since background it will give this error if i use handler
Swift: 'Completion handler blocks are not supported in background sessions. Use a delegate instead.'
- (void) startRequestWithURL:(NSURL *)url type:(XCDYouTubeRequestType)requestType
{
if (self.isCancelled)
return;
// Max (age-restricted VEVO) = 2×GetVideoInfo + 1×WatchPage + 1×EmbedPage + 1×JavaScriptPlayer + 1×GetVideoInfo
if (++self.requestCount > 6)
{
// This condition should never happen but the request flow is quite complex so better abort here than go into an infinite loop of requests
[self finishWithError];
return;
}
XCDYouTubeLogDebug(#"Starting request: %#", url);
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10];
[request setValue:self.languageIdentifier forHTTPHeaderField:#"Accept-Language"];
NSLog(#"Request Type - ",requestType);
// NEWLY ADDED
NSURLSessionDataTask *task = [self.session dataTaskWithRequest:request];
[task resume];
// self.dataTask = [self.session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error)
// {
// if (self.isCancelled)
// return;
//
// if (error)
// [self handleConnectionError:error];
// else
// [self handleConnectionSuccessWithData:data response:response requestType:requestType];
// }];
// [self.dataTask resume];
self.requestType = requestType;
}
the problem now is that i originally use this
self.dataTask = [self.session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error)
{
if (self.isCancelled)
return;
if (error)
[self handleConnectionError:error];
else
[self handleConnectionSuccessWithData:data response:response requestType:requestType];
}];
[self.dataTask resume];
which handleConnectionSuccessWithData will take in data, response and request type. Now i don't know where can i get the data, response and request type if i use backgroundSessionConfigurationWithIdentifier.
Use background thread instead of the main queue
backgroundSessionConfigurationWithIdentifier:
For reference
https://developer.apple.com/documentation/foundation/nsurlsessionconfiguration/1407496-backgroundsessionconfigurationwi?language=objc

Code Review for filling tableview cells with response returned from server

Connection Class
-(NSDictionary *)getResponseFromSearchByRoutewithUrl:(NSString *)url :(HttpCompletionBlock)completionHandler {
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
[urlRequest setHTTPMethod:#"GET"];
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSDictionary *responseDictionary;
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];
NSURLSessionDataTask *task = [session dataTaskWithRequest: urlRequest completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
//check if we encountered an error
if(error != nil){
NSLog(#"%#", [error localizedDescription]);
}else{
//get and check the HTTP status code
NSInteger HTTPStatusCode = [(NSHTTPURLResponse *)response statusCode];
if (HTTPStatusCode != 200) {
NSLog(#"HTTP status code = %ld", (long)HTTPStatusCode);
}
[task resume];
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
if(data != nil){
NSError *parseError = nil;
NSDictionary *responseDictionary = [NSJSONSerialization JSONObjectWithData:data options:0 error:&parseError];
NSLog(#"The response is - %#",responseDictionary);
return completionHandler(responseDictionary,nil);
}
else {
return completionHandler(nil,error);
}
}];
}
}];
[task resume];
return responseDictionary;
}
ViewController having Table view cells Class
-(void)viewDidLoad
{
_appDelegate= (AppDelegate *)[[UIApplication sharedApplication] delegate];
[[ConnectionManager sharedConnectionManager]getResponseFromSearchByRoutewithUrl:_urlString :^(NSDictionary *responseDictionary, NSError *error) {
if(error == nil)
{
_appDelegate.flightsArray=[responseDictionary objectForKey:#"scheduledFlights"];
NSLog(#"the flights array is%# ", _appDelegate.flightsArray);
}
else
{
NSLog(#"Error == %# ",error);
}
}];
}
Table View delegate class methods
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return _appDelegate.flightsArray.count;
}
Kindly Review the code and tell why the number of rows is zero...even when the response dictionary is returning dictionary...
try below code
-(void)viewDidLoad
{
_appDelegate= (AppDelegate *)[[UIApplication sharedApplication] delegate];
[[ConnectionManager sharedConnectionManager]getResponseFromSearchByRoutewithUrl:_urlString :^(NSDictionary *responseDictionary, NSError *error) {
if(error == nil)
{
_appDelegate.flightsArray=[responseDictionary objectForKey:#"scheduledFlights"];
NSLog(#"the flights array is%# ", _appDelegate.flightsArray);
[self performSelector:#selector(reloadTableview) withObject:nil afterDelay:0.2];
}
else
{
NSLog(#"Error == %# ",error);
}
}];
}
- (void)reloadTableview{
[self.tableview reloadData];
}

iOS - Why is this method so slow?

I have an iOS method that is now deprecated --NSURLConnection sendSynchronousRequest. This method worked and was fast.
I must be doing something wrong with the new method, as it is unacceptably slow.
The new method code I'm showing the whole routine is:
- (void)getData {
NSLog(#"%s", __FUNCTION__);
pathString = #"https://api.wm.com/json/jRoutes/.......";
NSURL *url = [NSURL URLWithString:pathString......];
NSURLSessionDataTask *downloadTask = [[NSURLSession sharedSession]
dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if ([response respondsToSelector:#selector(statusCode)]) {
if ([(NSHTTPURLResponse *) response statusCode] == 404) {
dispatch_async(dispatch_get_main_queue(), ^{
// alert
NSLog(#" NO DATA");
return;
});
}
}
// 4: Handle response here
[self processResponseUsingData:data];
}];
[downloadTask resume];
}
- (void)processResponseUsingData:(NSData*)data {
NSLog(#"%s", __FUNCTION__);
NSError *error = nil;
NSMutableDictionary* json = nil;
if(nil != data)
{
json = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];
}
if (error || !json)
{
NSLog(#"Could not parse loaded json with error:%#", error);
} else {
dispatch_async(dispatch_get_main_queue(), ^{
allRoutesArray = [json valueForKey:#"Routes"];
NSLog(#"allRoutesArray count: %lu", (unsigned long)allRoutesArray.count);
[self.tableView reloadData];
});
}
}

Make periodic server requests with NSURLSessionDataTask and dispatch_source timer

Need some help and explanation, because i'm really stuck in my question. i need to make this:
1) I make one request to the server, get some response and then i want to make another request every 7 seconds(example). also get some response. if it satisfy several conditions -> stop timer and do some stuff.
Main problem is that timer never stops, despite the fact that all in all i get response right. i assume that i use GCD incorrectly. because in debug this code behaves really strange.
What i have done:
This is my request function(it became like this after i read about 50 links how to do similar things)
-(void)makeRequestWithURL:(NSString*)urlString andParams:(NSString*)params andCompletionHandler:(void(^)(NSDictionary *responseData, NSError *error))completionHnadler{
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];
NSURL *url = [NSURL URLWithString:urlString];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url
cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
request.HTTPMethod = #"POST";
request.HTTPBody = [params dataUsingEncoding:NSUTF8StringEncoding];
NSURLSessionDataTask *postDataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (completionHnadler) {
if (error) {
dispatch_async(dispatch_get_main_queue(), ^{
completionHnadler(nil, error);
});
} else {
NSError *parseError;
json = [NSJSONSerialization JSONObjectWithData:data
options:NSJSONReadingMutableContainers
error:&parseError];
dispatch_async(dispatch_get_main_queue(), ^{
completionHnadler(json, parseError);
});
}
}
}];
[postDataTask resume]; }
I create my timer like this:
dispatch_source_t CreateDispatchTimer(uint64_t interval,
uint64_t leeway,
dispatch_queue_t queue ,
dispatch_block_t block) {
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
if (timer) {
// Use dispatch_time instead of dispatch_walltime if the interval is small
dispatch_source_set_timer(timer, dispatch_walltime(NULL, 0), interval, leeway);
dispatch_source_set_event_handler(timer, block);
dispatch_resume(timer);
}
return timer; }
and called it like this:
-(void)checkForPassenger {
timerSource = CreateDispatchTimer(7ull * NSEC_PER_SEC, 1ull * NSEC_PER_SEC, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
if([self getNotificationsRequest] == YES) {
dispatch_source_cancel(timerSource);
} else {
NSLog(#"go on timer");
}
NSLog(#"Driver checked for passenger!");
}); }
this is the code of periodic response:
-(BOOL)getNotificationsRequest {
NSString *urlString = #"http://primetime.by/temproad/do";
NSString *params = [NSString stringWithFormat:#"event={\"type\": \"in.getNotifications\"}&session_id=%#",session_id];
[self makeRequestWithURL:urlString andParams:params andCompletionHandler:^(NSDictionary *responseData, NSError *error) {
if ([[responseData objectForKey:#"rc"] intValue] == 0) {
NSArray *temp_notifications = [responseData objectForKey:#"notifications"];
if (temp_notifications.count != 0) {
notification = [[Notification alloc] initWithNotification:[[responseData objectForKey:#"notifications"] objectAtIndex:0]];
}
}
}];
if (notification) {
return YES;
} else {
return NO;
} }
and this is what i do in main request:
[self makeRequestWithURL:urlString andParams:params andCompletionHandler:^(NSDictionary *responseData, NSError *error) {
if ([[responseData objectForKey:#"rc"] intValue] == 0) {
route = [[Route alloc] initWithData:responseData];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self checkForPassenger];
});
}
}];
NSLog(#"bye");
maybe explanation is bad so i can answer any question.
thx

Problems with dispatch iOS

I'm new to iOS and I have trouble understanding and applying well dispatch ... I have an application I need to query a website (api) within a for loop, the end of that cycle I need to make further inquiries in another cycle, and finally, at the end of both cycles need to switch views.
I now have this code (after much trial and error but still does not work):
dispatch_queue_t queue = dispatch_queue_create("threadServicios", DISPATCH_QUEUE_SERIAL);
dispatch_group_t group = dispatch_group_create();
dispatch_group_enter(group);
dispatch_async(queue, ^(void) {
NSLog(#"llego a buscar servicios por local");
for (NSDictionary *local in _arrLocalesTmp) {
[self getListaServiciosPorLocal:[local objectForKey:#"idLocal"]];
//this function calls another function that consumes a web service and get a json
}
procced = YES;
NSLog(#"llego a buscar profesionales por local");
for (NSDictionary *local in _arrLocalesTmp) {
[self getListaProfesionalesPorLocal:[local objectForKey:#"idLocal"]];
//this function calls another function that consumes a web service and get a json
}
procced2 = YES;
dispatch_group_leave(group);
});
dispatch_group_notify(group, dispatch_get_main_queue(),^{
NSLog(#"dispatch procced 1");
if (procced && procced2) {
[self setFormularioConsultaCompleto];
}
});
The function [self getListaServiciosPorLocal: [Local objectForKey: # "idLocal"]]; is as follows:
dispatch_async(dispatch_get_main_queue(), ^(void) {
NSURL *url = [NSURL URLWithString:urlConnection];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
sessionConfiguration.timeoutIntervalForRequest = 30;
sessionConfiguration.timeoutIntervalForResource = 60;
NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration];
NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
__block NSError *jsonError;
NSHTTPURLResponse *urlResponse = (NSHTTPURLResponse *) response;
if(!error) {
if(urlResponse.statusCode == 200) {
NSDictionary *response = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:&jsonError];
if(response) {
NSString *resp = [NSString stringWithFormat:#"%#", [dataResponse objectForKey:#"resp"]];
if([resp isEqualToString:#"1"]) {
_json = [dataResponse objectForKey:#"data"];
[_arrServiciosTmp addObjectsFromArray:(NSArray *)_json];
} else {
NSString *message = [dataResponse objectForKey:#"description"];
}
} else {
self.lblMensaje.text = #"Ha ocurrido un error al obtener la información, por favor, vuelva a intentarlo en unos momentos.";
}
} else {
completion(nil);
}
} else {
NSLog(#"Error en Task");
}
});
And the function [self getListaProfesionalesPorLocal: [Local objectForKey: # "idLocal"]]; is similar but obtains other information
The problem is that the app calls this function [self setFormularioConsultaCompleto]; (changing the view) but the above functions still do not quite get all the data from webservice.
Sorry for this, but I gave up, I hope can help me!
Thanks!
The below uses dispatch groups to hold off starting another block till the groups work has been completed.
First change your data methods to not be wrapped in dispatch_async and accept a completion block, calling that at the end of the NSURLSessionDataTasks completionHandler:
-(void)getListaServiciosPorLocal:(id)whatEver withCompletionBlock:(dispatch_block_t)block
{
NSURL *url = [NSURL URLWithString:urlConnection];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
sessionConfiguration.timeoutIntervalForRequest = 30;
sessionConfiguration.timeoutIntervalForResource = 60;
NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration];
NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
__block NSError *jsonError;
NSHTTPURLResponse *urlResponse = (NSHTTPURLResponse *) response;
if(!error) {
if(urlResponse.statusCode == 200) {
NSDictionary *response = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:&jsonError];
if(response) {
NSString *resp = [NSString stringWithFormat:#"%#", [dataResponse objectForKey:#"resp"]];
if([resp isEqualToString:#"1"]) {
_json = [dataResponse objectForKey:#"data"];
[_arrServiciosTmp addObjectsFromArray:(NSArray *)_json];
} else {
NSString *message = [dataResponse objectForKey:#"description"];
}
} else {
self.lblMensaje.text = #"Ha ocurrido un error al obtener la información, por favor, vuelva a intentarlo en unos momentos.";
}
} else {
completion(nil);
}
} else {
NSLog(#"Error en Task");
}
block(); // Notify completion block
});
}
Now when you call these methods:
dispatch_group_t group = dispatch_group_create();
dispatch_async(queue, ^(void) {
NSLog(#"llego a buscar servicios por local");
for (NSDictionary *local in _arrLocalesTmp) {
dispatch_group_enter(group);
[self getListaServiciosPorLocal:[local objectForKey:#"idLocal"] withCompletionBlock:^{
dispatch_group_leave(group);
}];
}
NSLog(#"llego a buscar profesionales por local");
for (NSDictionary *local in _arrLocalesTmp) {
dispatch_group_enter(group);
[self getListaProfesionalesPorLocal:[local objectForKey:#"idLocal"] withCompletionBlock:^{
dispatch_group_leave(group);
}];
}
});
dispatch_group_notify(group, dispatch_get_main_queue(),^{
[self setFormularioConsultaCompleto];
});
(Adapted from this answer)

Resources