Why NSURLConnection didReceiveData not be called in background location update - ios

Please help me, I am coding iOS with background location update and send location data to my server.
below is my code:
#import "AppDelegate.h"
#implementation AppDelegate
- (void)applicationDidEnterBackground:(UIApplication *)application
{
NSLog(#"Went to Background");
[locationManager startMonitoringSignificantLocationChanges];
[locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
UIApplication *app = [UIApplication sharedApplication];
__block UIBackgroundTaskIdentifier locationUpdateTaskID = [app beginBackgroundTaskWithExpirationHandler:^{
dispatch_async(dispatch_get_main_queue(), ^{
if (locationUpdateTaskID != UIBackgroundTaskInvalid) {
[app endBackgroundTask:locationUpdateTaskID];
locationUpdateTaskID = UIBackgroundTaskInvalid;
}
});
}];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
if ([[locations lastObject] horizontalAccuracy] < 100.0f) {
NSUserDefaults *userDefaults=[NSUserDefaults standardUserDefaults];
mytoken=[userDefaults stringForKey:#"mytoken"];
if (mytoken==nil) {
mytoken=#"";
}
mybgtype=[userDefaults stringForKey:#"mybgtype"];
if (mybgtype==nil) {
mybgtype=#"all";
[userDefaults setObject:mybgtype forKey:#"mybgtype"];
[userDefaults synchronize];
}
CLLocation *newLocation = [locations lastObject];
CLLocation *oldLocation;
if (locations.count > 1) {
oldLocation = [locations objectAtIndex:locations.count-2];
} else {
oldLocation = nil;
}
NSString *NowLng=[[NSNumber numberWithFloat:newLocation.coordinate.longitude] stringValue];
NSString *NowLat=[[NSNumber numberWithFloat:newLocation.coordinate.latitude] stringValue];
UILocalNotification *scheduleAlert;
[[UIApplication sharedApplication] cancelAllLocalNotifications];
scheduleAlert=[[UILocalNotification alloc] init];
scheduleAlert.applicationIconBadgeNumber=1;
scheduleAlert.fireDate=[NSDate dateWithTimeIntervalSinceNow:1];
scheduleAlert.timeZone=[NSTimeZone defaultTimeZone];
scheduleAlert.repeatInterval=NSDayCalendarUnit;
scheduleAlert.soundName=UILocalNotificationDefaultSoundName;
scheduleAlert.alertBody=NowLat;
[[UIApplication sharedApplication] scheduleLocalNotification:scheduleAlert];
if ([mybgtype isEqualToString:#"n"]) {
} else {
[self LoadTaskMyBg:newLocation];
}
}
dispatch_async(dispatch_get_main_queue(), ^{
if (locationUpdateTaskID != UIBackgroundTaskInvalid) {
[app endBackgroundTask:locationUpdateTaskID];
locationUpdateTaskID = UIBackgroundTaskInvalid;
}
});
});
}
-(void) LoadTaskMyBg:(CLLocation *)newLocation
{
NSString *mylat = [NSString stringWithFormat:#"%.8f", newLocation.coordinate.latitude];
NSString *mylng = [NSString stringWithFormat:#"%.8f", newLocation.coordinate.longitude];
NSLog(#"task 1");
receivedDataMyBg=[[NSMutableData alloc] initWithLength:0];
NSString * urlString;
urlString = #"https://www.xx.xx/xx.cshtml";
NSURL * url = [NSURL URLWithString:urlString];
NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:15.0];
[request setHTTPMethod:#"POST"];
NSString *parameterString=[NSString stringWithFormat:#"%#%#%#%#%#%#%#%#", #"pp=a&tt=",#"aa",#"&mylat=",mylat,#"&mylng=",mylng,#"&myalt=",#"0"];
NSData * postData = [parameterString dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPBody:postData];
connMyBg = [[NSURLConnection alloc] initWithRequest:request delegate:self];
NSLog(#"task 1a");
NSLog(#"%#",parameterString);
if (connMyBg==nil) {
NSLog(#"task 1e");
return;
}
}
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace{
return YES;
}
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge{
//NSLog(#"received authen challenge");
NSLog(#"task challenge");
[challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
if (connection==connMyBg) {
[receivedDataMyBg setLength:0];
NSLog(#"task connect receive");
}
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
//NSLog(#"got data %#", [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease]);
if (connection==connMyBg) {
[receivedDataMyBg appendData:data];
}
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
NSLog(#"error");
if (connection==connMyBg) {
}
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
if (connection==connMyBg) {
NSLog(#"task 2");
NSString *response;
NSError *error;
response=[[NSString alloc] initWithData:receivedDataMyBg encoding:NSUTF8StringEncoding];
NSData* data = [response dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *JSONDic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:&error];
if([[JSONDic objectForKey:#"bnum"] isEqualToString:#""])
{
} else {
UILocalNotification *scheduleAlert;
[[UIApplication sharedApplication] cancelAllLocalNotifications];
scheduleAlert=[[UILocalNotification alloc] init];
scheduleAlert.applicationIconBadgeNumber=1;
scheduleAlert.fireDate=[NSDate dateWithTimeIntervalSinceNow:1];
scheduleAlert.timeZone=[NSTimeZone defaultTimeZone];
scheduleAlert.repeatInterval=NSDayCalendarUnit;
scheduleAlert.soundName=UILocalNotificationDefaultSoundName;
scheduleAlert.alertBody=#"TEST:OK";
}
NSLog(#"%#",[JSONDic objectForKey:#"bnum"]);
}
}
#end
I can get log: "task 1a" ! but why I can't receive "task connect receive" ????
What should I do ?
Thanks.

To use a delegate for either NSURLConnection or CLLocationManager you'll need to create them as properties with a strong reference. Otherwise the delegate implementation will not get called. Since you did not provide the part where you declared those that may be the problem.

NSString* pp =[NSString stringWithFormat:#"xxxx.xx/xx.cshtml, newLocation.coordinate.latitude, newLocation.coordinate.longitude,0.0];
NSURL* response =[NSURL URLWithString:pp];
NSString* response_str =[NSString stringWithContentsOfURL:response encoding:NSUTF8StringEncoding error:nil];
NSLog(#"%#, response of report=%#", pp, response_str);
If I rewrite the code in didUpdateLocations as above,
I can get response_str and it is correct!
But question is: How can it pass ssl https without be challenged ??
even if it ready work very well!

Related

NSURLSession didReceiveChallenge called for each request

I am using this custom class to download data from Server(ASP.NET IIS 7.5) using a certificate. It works just fine except that on every request the didReceiveChallenge method is called every time and credentials has to be applied again and again. The performance suffers greatly.
How can we avoid this?
Thanks.
#import "ServerRequest.h"
#import <UIKit/UIKit.h>
#implementation ServerRequest{
NSMutableData * recievedData;
NSString * operationName;
NSString * operationParameters;
DataOperationType operationType;
NSURL* downloadURL;
NSData * HTTPBodyData;
UIView * waitView;
UIProgressView * progressView;
}
- (instancetype)init{
if(self = [super init]) {
}
return self;
}
- (NSURLSession *)normalSession{
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLProtectionSpace * protectionSpace = [[NSURLProtectionSpace alloc] initWithHost:[Config getBaseURL] port:443 protocol:#"https" realm:nil authenticationMethod:NSURLAuthenticationMethodClientCertificate];
[configuration.URLCredentialStorage setDefaultCredential:[Helper getCredential] forProtectionSpace:protectionSpace];
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:[NSOperationQueue mainQueue]];
return session;
}
- (instancetype)initWithRequest:(NSString *)request
{
if(self = [super init]) {
operationType = DataOperationTypeData;
downloadURL = [NSURL URLWithString:request];
NSLog(#"Created download operation for URL: %#", [downloadURL absoluteString]);
}
return self;
}
- (instancetype)initWithRequest:(NSString *)request Dicionary:(NSString *) dataDictionary{
if(self = [super init]) {
operationType = DataOperationTypeHTMLFrom;
downloadURL = [NSURL URLWithString:request];
NSLog(#"Created download operation for URL: %#", [downloadURL absoluteString]);
operationParameters = dataDictionary;
}
return self;
}
- (instancetype)initWithRequest:(NSString *)request data:(NSData *) bodyData{
if(self = [super init]) {
operationType = DataOperationTypeBodyData;
downloadURL = [NSURL URLWithString:request];
NSLog(#"Created download operation for URL: %#", [downloadURL absoluteString]);
HTTPBodyData = bodyData;
}
return self;
}
- (void) performOperationWithCompletion:(ServerRequestCompletion)onCompletion error:(ServerRequestError)onError{
if (self.showProgressView){
[self configureProgressView];
}
if (self.parentView) {
waitView = [Config createWaitView:self.parentView];
}
self.completion = onCompletion;
self.error = onError;
NSMutableURLRequest *request;
request = [NSMutableURLRequest requestWithURL:downloadURL];
[request setHTTPMethod:#"POST"];
[request setValue:#"utf-8" forHTTPHeaderField:#"Accept-Charset"];
if (operationType == DataOperationTypeHTMLFrom) {
NSData *postData = [operationParameters dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPMethod:#"POST"];
[request setValue:#"utf-8" forHTTPHeaderField:#"Accept-Charset"];
[request setValue:[NSString stringWithFormat:#"%ld", (unsigned long)postData.length] forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/x-www-form-urlencoded charset=utf-8" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:postData];
}
else if (operationType == DataOperationTypeBodyData) {
[request setHTTPMethod:#"POST"];
[request setValue:[NSString stringWithFormat:#"%ld", (unsigned long)HTTPBodyData.length] forHTTPHeaderField:#"Content-Length"];
[request addValue: #"multipart/form-data; charset=utf-8" forHTTPHeaderField: #"Content-Type"];
[request setHTTPBody:HTTPBodyData];
}
else{
[request setValue:#"application/x-www-form-urlencoded charset=utf-8" forHTTPHeaderField:#"Content-Type"];
}
NSURLSession * defaultSession = [self normalSession];
NSURLSessionTask * dataTask = [defaultSession dataTaskWithRequest:request];
if (!dataTask) {
self.error([EXError errorWithDomain:[[NSBundle mainBundle] bundleIdentifier] code:-1 userInfo:#{NSLocalizedDescriptionKey: #"Could not initialize connection"}]);
}else{
if (self.showProgressView) {
dispatch_async(dispatch_get_main_queue(), ^{
// AppDelegate_Shared * appDelegate = (AppDelegate_Shared *)([UIApplication sharedApplication]).delegate;
// [appDelegate.progressView setHidden:NO];
// [appDelegate.progressView setProgress:0];
});
}
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
[dataTask resume];
}
}
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler{
//NSURLProtectionSpace *protectionSpace = [challenge protectionSpace];
NSURLCredential *credential = [Helper getCredential];
if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodNTLM])
{
if (challenge.previousFailureCount >= 3)
{
// handle the fact that the previous attempt failed
EXError* error = [EXError errorWithDomain:NSURLErrorDomain code:403 userInfo: #{NSLocalizedDescriptionKey: #"Unable to verify account information."}];
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
self.error(error);
}else{
NSURLCredentialPersistence persistence = NSURLCredentialPersistenceForSession;
NSString * userName = [Config getUserName];
NSString * password = [Config getPassword];
NSURLCredential *loginCredential = [NSURLCredential credentialWithUser:userName password:password persistence:persistence];
completionHandler(NSURLSessionAuthChallengeUseCredential, loginCredential);
[self removeWaitView];
}
}
else if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
{
completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
//completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
[self removeWaitView];
}
else if ([[challenge protectionSpace] authenticationMethod] == NSURLAuthenticationMethodClientCertificate)
{ NSLog(#"\n______________________________________________________ Authentication Method Client Certificate _________________________________________________");
completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
[self removeWaitView];
}
else{
completionHandler(NSURLSessionAuthChallengeRejectProtectionSpace, nil);
[self removeWaitView];
}
}
-(void) configureProgressView{
UIViewController * topController = [Helper currentTopViewController];
if (![topController isKindOfClass:[UINavigationController class]]) {
return;
}
UINavigationController * navigationController = (UINavigationController *)topController;
UINavigationBar * navigationBar = [navigationController navigationBar];
progressView = [[UIProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleBar];
progressView.frame = CGRectMake(navigationBar.frame.origin.x, navigationBar.frame.size.height - 5, navigationBar.frame.size.width, 5);
[navigationBar addSubview:progressView];
}
-(void) removeWaitView{
[waitView removeFromSuperview];
waitView = nil;
}
- (void)URLSession:(NSURLSession *)session didBecomeInvalidWithError:(NSError *)error{
}
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
didReceiveResponse:(NSURLResponse *)response
completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler
{
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
NSDictionary *responseHeaders = ((NSHTTPURLResponse *)response).allHeaderFields;
NSLog(#"headers: %#", responseHeaders.description);
if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
if (httpResponse.statusCode >= 400) { // Client/Server Error
EXError * error = [EXError errorWithDomain:[[NSBundle mainBundle] bundleIdentifier] code:httpResponse.statusCode userInfo:#{NSLocalizedDescriptionKey: [NSHTTPURLResponse localizedStringForStatusCode:httpResponse.statusCode]}];
self.error(error);
NSLog(#"Failed with Error %ld : %#", (long)httpResponse.statusCode, [NSHTTPURLResponse localizedStringForStatusCode:httpResponse.statusCode]);
completionHandler(NSURLSessionResponseAllow);
[self removeWaitView];
return;
}
}
completionHandler(NSURLSessionResponseAllow);
[self removeWaitView];
}
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data{
if (!recievedData) {
recievedData = [NSMutableData new];
}
[recievedData appendData:data];
if ([dataTask countOfBytesExpectedToReceive] !=NSURLSessionTransferSizeUnknown) {
double progress = (double)[dataTask countOfBytesReceived] / (double) [dataTask countOfBytesExpectedToReceive];
if (self.showProgressView) {
dispatch_async(dispatch_get_main_queue(), ^{
[progressView setProgress:progress animated:YES];
});
}
}
// DLog(#"progress : %lld", [dataTask countOfBytesExpectedToReceive]);
}
//- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
// didSendBodyData:(int64_t)bytesSent
// totalBytesSent:(int64_t)totalBytesSent
// totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend{
// // DLog(#"Did Sent %f", (double)totalBytesSent);
//
// if (self.showProgressView) {
//
// dispatch_async(dispatch_get_main_queue(), ^{
//
// AppDelegate_Shared * appDelegate = (AppDelegate_Shared *)([UIApplication sharedApplication]).delegate;
// [appDelegate.progressView setProgress:
// (double)totalBytesSent /
// (double)totalBytesExpectedToSend animated:YES];
//
// });
// }
//}
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
if (self.showProgressView) {
dispatch_async(dispatch_get_main_queue(), ^{
[progressView setHidden:YES];
});
}
// NSString *myString = [[NSString alloc] initWithData:recievedData encoding:NSUTF8StringEncoding];
//
// NSLog(#"%#", myString);
if(error == nil)
{
// SBJSON *json = [SBJSON new];
// NSString *responseString = [[NSString alloc] initWithData:recievedData encoding:NSUTF8StringEncoding];
//
// //NSLog(#"Finished (%#) %d bytes. %#", [downloadURL absoluteString], [data length], responseString);
//
// NSDictionary *dataSet = [json objectWithString:responseString];
NSDictionary* dataSet = [NSJSONSerialization
JSONObjectWithData:recievedData
options:kNilOptions
error:&error];
self.completion(dataSet);
}
else{
// if (error.code == -999) {
// return;
// }
// NSString * httpBody = [[NSString alloc] initWithData:task.currentRequest.HTTPBody encoding:NSUTF8StringEncoding];
//
// httpBody = [NSString stringWithFormat:#"%s\n%#", __PRETTY_FUNCTION__, httpBody];
// [Helper MsgBox:httpBody];
EXError * exError = [EXError errorWithDomain:error.domain code:error.code userInfo:#{NSLocalizedDescriptionKey: [NSHTTPURLResponse localizedStringForStatusCode:error.code]}];
self.error(exError);
// DLog(#"Error %#", [error localizedDescription]);
}
}
#end
One of the reasons can be a check of HTTPS the certificate.
Apple Documentation
This instance contains a protectionSpace property whose authenticationMethod property indicates the kind of challenge being issued (such as a request for a username and password, or a client certificate). You use this value to determine whether you can handle the challenge.
Adding this precondition can check the authentication method and call the handler.
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
completionHandler(NSURLSessionAuthChallengeUseCredential, nil);
return;
}
You can find authentication methods constants here

How to send data to server and receive response in same methood

Im new to ios i have a doubt that i want to send data to server and receive response in same method
i have a class name
profile.m and i want to send data to service class and receive response in profile class
Profile.m:
NSString *parameter = [NSString stringWithFormat:#"%#&access_token=%#&lksite=social&lkmenu=profile&lktype=view&displayedname=%#&displayid=%#", baseUrl, accessToken, userName,userId];
Service *service = [[Service alloc]init];
[service sendDataToServer:#"POST" andUrl:parameter andUrl:baseUrl];
Service.m
-(void) sendDataToServer:(NSString *) method andUrl:(NSString *) getUrl andUrl:(NSString *)baseUrl{
NSMutableData *jsondata;
Session *ses =[[Session alloc]init];
accessToken = [ses getAccessToken];
NSLog(#"Access Token---> %#",accessToken);
NSString *baseUrl1 = [NSString baseUrl];
if([method isEqualToString:#"GET"]){
NSString *urlStr = [NSString stringWithFormat: #"%#&access_token=%#",getUrl,accessToken];
url = [NSURL URLWithString: urlStr];
urlRequest= [NSMutableURLRequest requestWithURL:url];
urlRequest.HTTPMethod=method;
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:urlRequest delegate:self];
if( connection )
{
urlMutable = [NSMutableData new];
}
}else{
NSData *parameterData = [getUrl dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
url = [NSURL URLWithString: baseUrl1];
urlRequest=[NSMutableURLRequest requestWithURL:url];
urlRequest.HTTPBody=parameterData;
urlRequest.HTTPMethod=method;
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:urlRequest delegate:self];
if( connection )
{
urlMutable = [NSMutableData new];
}
}}
You can user NSLocalNotification to achieve your task.
There are three simple steps to use NSLocalNotification.
1) For this you can write your code in Profile.m file as:
- (void)viewDidLoad {
[super viewDidLoad];
Service *Service = [[Service alloc] init];
[Service sendDataToServer:(with your parameters here)];
}
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(responceMethod:) name:#"WebServiceCall" object:nil];
}
2) in your Service.m class make a service call
-(void) sendDataToServer:(NSString *) method andUrl:(NSString *) getUrl andUrl:(NSString *)baseUrl{
NSMutableData *jsondata;
Session *ses =[[Session alloc]init];
accessToken = [ses getAccessToken];
NSLog(#"Access Token---> %#",accessToken);
NSString *baseUrl1 = [NSString baseUrl];
if([method isEqualToString:#"GET"]){
NSString *urlStr = [NSString stringWithFormat: #"%#&access_token=%#",getUrl,accessToken];
url = [NSURL URLWithString: urlStr];
urlRequest= [NSMutableURLRequest requestWithURL:url];
urlRequest.HTTPMethod=method;
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:urlRequest delegate:self];
if( connection )
{
urlMutable = [NSMutableData new];
}
}else{
NSData *parameterData = [getUrl dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
url = [NSURL URLWithString: baseUrl1];
urlRequest=[NSMutableURLRequest requestWithURL:url];
urlRequest.HTTPBody=parameterData;
urlRequest.HTTPMethod=method;
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:urlRequest delegate:self];
if( connection )
{
urlMutable = [NSMutableData new];
}
}
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*) response;
int errorCode = (int)httpResponse.statusCode;
NSLog(#"response is %d", errorCode);
[urlMutable setLength: 0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[urlMutable appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(#"Connection failed! Error - %# %#", [error localizedDescription], [[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]);
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSError *error;
id *response = [NSJSONSerialization JSONObjectWithData:webData options:NSJSONReadingAllowFragments error:&error];
[[NSNotificationCenter defaultCenter] postNotificationName:#"WebServiceCall" object:nil userInfo:response];
}
And finally
3) Implement your response parsing here in the method you have written in Profile.m file like:
-(void)responceMethod:(NSNotification *)notif{
NSDictionary *dict = [notif userInfo];
// Your response parsing.
}
Declare a block as :
typedef void (^completionBlock)(id responseObject , NSError *error);
And then add this block to your methods as :
- (void) performRequestWithCompletion:(completionBlock)block;
On invoking this method, will return you "responseObject" and "error". error nil in case of success

When changing view controllers NSURLConnection delegate not updating the progress bar

I am performing a download through NSURLConnection class and updating a progress bar view according to the received bytes in the NSURLConnection delegate connection didReceiveData.
Everything is working fine when I am on the page where downloading is happening but when I am going to some other view controller and coming back to my downloading page, the connection delegate functions are being called while transition of page but coming back does not upgrade the progress bar.
The code I am using is:
- (IBAction)download:(id)sender {
_currentURL = [NSString stringWithFormat:#"url_to_download"];
NSURL *url =[NSURL URLWithString:_currentURL];
NSURLRequest *theRequest = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:60];
_receivedData = [[NSMutableData alloc]initWithLength:0];
connection2 = [[NSURLConnection alloc]initWithRequest:theRequest delegate:self startImmediately:YES];
}
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
NSLog(#"THE STATUS CODE IS %d",[httpResponse statusCode]);
statuscode = [httpResponse statusCode];
NSLog(#"into didReceiveResponse");
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
[_receivedData setLength:0];
expectedBytes = [response expectedContentLength];
NSLog(#"EXPECTED BYTES:%ld",expectedBytes);
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
NSLog(#"into did receivedata");
[_receivedData appendData:data];
self.setting.enabled = NO;
float progressive = (float)[_receivedData length] / (float)expectedBytes;
[self.progress setProgress:progressive];
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
AppDelegate *app = (AppDelegate*) [[UIApplication sharedApplication]delegate];
NSLog(#"into didfailwitherror");
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
NSLog(#"connection failed");
}
-(NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse
{
return nil;
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
self.setting.enabled = YES;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSLog(#"DOCUMENT DIRECTORY :%#",documentsDirectory);
_imagePath = [documentsDirectory stringByAppendingPathComponent:_fullPath];
NSLog(#"iamge path:%#",_imagePath);
NSLog(#"succeeded");
[UIApplication sharedApplication].networkActivityIndicatorVisible= NO;
NSLog(#"Succeeded! Received %d bytes of data",[_receivedData length]);
// flag= [_receivedData writeToFile:imagePath atomically:NO];
if([_receivedData writeToFile:_imagePath atomically:YES])
{
NSLog(#"write successfull");
app.dl_status = 0;
[HUD hide:YES];
[HUD removeFromSuperview];
HUD = nil;
[self completedDownloadHUD];
[self.download setBackgroundImage:[UIImage imageNamed:#"download.png"] forState:UIControlStateNormal];
}
else{
app.dl_status = 0;
NSLog(#"write failed");
[HUD hide:YES];
[self errorDownloadHUD];
}
NSString *imagePathExtension;
imagePathExtension = [_imagePath pathExtension];
if([imagePathExtension isEqual:#"jpg"])
{
NSLog(#"imagepathextension is jpg");
UIImage *img =[UIImage imageWithContentsOfFile:_imagePath];
UIImageWriteToSavedPhotosAlbum(img, self, #selector(image:didFinishSavingWithError:contextInfo:), NULL);
}
else if([imagePathExtension isEqual:#"mov"])
{
NSLog(#"imagepathextension is mp4");
UISaveVideoAtPathToSavedPhotosAlbum(_imagePath, nil, nil, nil);
}
}
Please tell me how i can retain the value of progress bar while coming back to page and update it.
Change your delegate to this then update the question. I suspect you will find something gets hit with the asserts:
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
NSLog(#"into didReceiveData");
[_receivedData appendData:data];
assert(_receivedData); // it exists
assert([_receivedData length]); // it also has some data in it
self.setting.enabled = NO;
float progressive = (float)[_receivedData length] / (float)expectedBytes;
assert(expectedBytes > 0);
assert(progressive > 0 && progressive <= 1);
assert(self.progress);
assert(!self.progress.hidden);
assert(!self.progress.alpha > 0.5);
assert(self.progress.window);
[self.progress setProgress:progressive];
}
If you don't get any asserts, you still are getting delegate messages, and the progress bar is not visible (or not moving) then log the value of progressive and/or the progress bar frame.

IOS7 NSURLConnection nothing happens

I am quite a newbie to IOS programming and want to user's location to server. I followed iOS developer library and tutorials on the Internet but nothing happens when I run the code. I am using the iOS simulator and it gives me mock locations well and I get NSURLConnection instance. However, nothing happens on server-side.
#import "JLSViewController.h"
#import <CoreLocation/CoreLocation.h>
#import "JLSEventData.h"
#interface JLSViewController ()
#property (nonatomic, strong) CLLocationManager *locationManager;
#property (nonatomic, strong) NSMutableArray *locations;
#end
#implementation JLSViewController
NSMutableData *responseData = nil;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.locations = [[NSMutableArray alloc] init];
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
self.locationManager.delegate = self;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)enabledStateChanged:(id)sender
{
if (self.switchEnabled.on)
{
[self.locationManager startUpdatingLocation];
}
else
{
[self.locationManager stopUpdatingLocation];
}
}
- (void)beginBackgroundUpdateTask: (CLLocation *)location {
}
- (void)endBackgroundUpdateTask {
}
#pragma mark - CLLocationManagerDelegate
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation {
if (newLocation == nil) {
return;
}
if (oldLocation != nil) {
if (newLocation.coordinate.latitude == oldLocation.coordinate.latitude &&
newLocation.coordinate.longitude == oldLocation.coordinate.longitude) {
return;
}
}
NSError *error = nil;
JLSEventData *eventData = [[JLSEventData alloc] initWithLocation: newLocation];
NSString *strData = [eventData toJSON:error];
if (error != nil){
return;
}
if (self.locations.count>5)
[self.locations removeObjectAtIndex:0];
[self.locations addObject:strData];
NSData *requestBodyData = [NSJSONSerialization dataWithJSONObject:self.locations options:NSJSONWritingPrettyPrinted error:&error];
if (error != nil){
return;
}
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//[self beginBackgroundUpdateTask:newLocation];
// Send a synchronous request
NSMutableURLRequest * urlRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString: "http://localhost:8080/mywebservice"]];
[urlRequest setValue:#"application/json; charset=utf-8" forHTTPHeaderField:#"Content-Type"];
[urlRequest setValue:#"application/json" forHTTPHeaderField:#"Accept"];
[urlRequest setHTTPMethod:#"POST"];
//[urlRequest setTimeoutInterval:20];
//NSJSONSerialization dataWithJSONObject
urlRequest.HTTPBody = requestBodyData;
// Create url connection and fire request
[urlRequest setHTTPBody:[NSData dataWithBytes:[strData UTF8String] length:strlen([strData UTF8String])]];
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:urlRequest delegate:self];
if (conn!=nil){
//receivedData = nil;
}
});
}
#pragma mark - NSURLConnection Delegate
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
NSLog(#"==>didReceiveResponse");
// A response has been received, this is where we initialize the instance var you created
// so that we can append data to it in the didReceiveData method
// Furthermore, this method is called each time there is a redirect so reinitializing it
// also serves to clear it
responseData = [[NSMutableData alloc] init];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
NSLog(#"==>didReceiveData");
// Append the new data to the instance variable you declared
[responseData appendData:data];
}
- (NSCachedURLResponse *)connection:(NSURLConnection *)connection
willCacheResponse:(NSCachedURLResponse*)cachedResponse {
// Return nil to indicate not necessary to store a cached response for this connection
return nil;
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
// The request is complete and data has been received
// You can parse the stuff in your instance variable now
NSLog(#"Succeeded! Received %d bytes of data",[responseData length]);
responseData = nil;
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
// The request has failed for some reason!
// Check the error var
NSLog(#"Connection failed! Error - %# %#",
[error localizedDescription],
[[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]);
}
/*
*
*/
- (void)parseData {
//Do something
}
#end
Any help would be appreciated.
You are doing the NSURLConnection on a separate thread. And the thread is exiting before the response is received. You either need to do the NSURLConnection on the main thread or you need to keep the thread running until the response is received.

Show Activity Indicator when fetching JSON data

I am beginner in IOS programming. My question is my app fetching data from JSON in my web server, when starting the apps, it is slightly lag and delay due to the fetching process, so i would like to show activity indicator when i connecting to JSON data. How can i do that?
My JSON coding:
- (void)viewDidLoad
{
[super viewDidLoad];
NSURL *urlAddress = [NSURL URLWithString:#"http://emercallsys.webege.com/RedBoxApp/getEvents.php"];
NSStringEncoding *encoding = NULL;
NSError *error;
NSString *jsonreturn = [[NSString alloc] initWithContentsOfURL:urlAddress usedEncoding:encoding error:&error];
NSData *jsonData = [jsonreturn dataUsingEncoding:NSUTF32BigEndianStringEncoding];
NSDictionary * dict = [[CJSONDeserializer deserializer] deserializeAsDictionary:jsonData error:&error];
if (dict)
{
eventsDetail = [[dict objectForKey:#"eventsDetail"] retain];
}
[jsonreturn release];
}
use the following code
//add a UIActivityIndicatorView to your nib file and add an outlet to it
[indicator startAnimating];
indicator.hidesWhenStopped = YES;
dispatch_queue_t queue = dispatch_get_global_queue(
DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
//Load the json on another thread
NSString *jsonreturn = [[NSString alloc] initWithContentsOfURL:urlAddress usedEncoding:encoding error:NULL];
[jsonreturn release];
//When json is loaded stop the indicator
[indicator performSelectorOnMainThread:#selector(stopAnimating) withObject:nil waitUntilDone:YES];
});
You can use something like below code:
- (void)fetchData
{
[activityIndicator startAnimating];
NSURL *url = [NSURL URLWithString:strUrl];
NSURLRequest *theRequest = [[NSURLRequest alloc]initWithURL:url];
NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
if(theConnection) {
}
else {
NSLog(#"The Connection is NULL");
}
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
webData = [[NSMutableData data] retain];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[webData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(#"ERROR with theConenction %#",error);
UIAlertView *connectionAlert = [[UIAlertView alloc] initWithTitle:#"Information !" message:#"Internet / Service Connection Error" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[connectionAlert show];
[connectionAlert release];
[connection release];
[webData release];
return;
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
//NSString *theXML = [[NSString alloc] initWithBytes: [webData mutableBytes] length:[webData length] encoding:NSUTF8StringEncoding];
//NSLog(#"Received data :%#",theXML);
//[theXML release];
NSDictionary * dict = [[CJSONDeserializer deserializer] deserializeAsDictionary: webData error:&error];
if (dict) {
eventsDetail = [[dict objectForKey:#"eventsDetail"] retain];
}
[activityIndicator stopAnimating];
}

Resources