how to access json data assigned to property in user defined method - ios

I am working on the google maps where I find the location based on the text entered in the
textfield.I have used NSConnection to find the location json and then I assign this json to
the property in connectionDidFinishLoading delegate method so that I can access the json
when it is required but unfortunately I am not getting the data in geocodeAddress
method(NSLog(#"geodata %#",geocode))
Can any one help me to fix this issue?
- (void)geocodeAddress:(NSString *)address withCallback:(SEL)callback withDelegate: (id)delegate
{
NSString *geocodingBaseUrl = #"http://maps.googleapis.com/maps/api/geocode/json?";
NSString *url = [NSString stringWithFormat:#"%#address=%#&sensor=false", geocodingBaseUrl,address];
NSLog(#"url=%#",url);
url = [url stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding];
NSURL *queryUrl = [NSURL URLWithString:url];
NSURLRequest *request =[NSURLRequest requestWithURL:queryUrl cachePolicy:NSURLCacheStorageNotAllowed timeoutInterval:10];
//NSURLRequest *request =[NSURLRequest requestWithURL:url];
downloaddata= [[NSMutableData alloc]init];
NSURLConnection *connection =[[NSURLConnection alloc] initWithRequest:request delegate:self];
NSLog(#"geodata %#",geocode);
//[delegate performSelector:callback];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSError *error;
alldata = [NSJSONSerialization
JSONObjectWithData:self->downloaddata
options:NSJSONReadingMutableContainers
error:&error];
if(error)
{
}
else
{
self.geocode =alldata;
//NSLog(#"geodata %#",geocode);
}
}

NSURLConnection's are normally asynchronous, so geocode isn't set until the connectionDidFinishLoading is called, which won't happen until sometime after geocodeAddress... has finished. In your connectionDidFinishLoading... you'll need to execute code to cause the UI to refresh with the now valid geocode data.
Alternatively you could use + (NSData *)sendSynchronousRequest:(NSURLRequest *)request returningResponse:(NSURLResponse **)response error:(NSError **)error to execute the request synchronously, but that would be bad since it would block the UI until the request completed.

Related

From NSURLConnection to NSURLSession

What is the best way to convert NSURLConnection to NSURLSession ?
error message: (Xcode)
ViewController.m:342:45: 'stringByAddingPercentEscapesUsingEncoding:' is deprecated: first deprecated in iOS 9.0 - Use -stringByAddingPercentEncodingWithAllowedCharacters: instead, which always uses the recommended UTF-8 encoding, and which encodes for a specific URL component or subcomponent since each URL component or subcomponent has different rules for what characters are valid.
my code :
-(void)downloadZip
{
NSLog(#"Start Downloading Zip File");
NSDate *myDate = (NSDate *)[[NSUserDefaults standardUserDefaults] objectForKey:#"LastUpdate"];
NSString *path = [NSString stringWithFormat:phpLinkgetZip, myDate];
NSURL *url = [NSURL URLWithString:[path stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSLog(#"Checking update at Zip File : %#", path);
NSLog(#"Checking update Time : %#", myDate);
responseData = [[NSMutableData alloc] init];
NSURLRequest* updateRequest = [NSURLRequest requestWithURL: url];
NSURLConnection* connection = [[NSURLConnection alloc] initWithRequest:updateRequest delegate:self];
[connection start];
NSLog(#"Zip Downloading start...");
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
[responseData setLength:0];
filesize = [[NSNumber numberWithLong: [response expectedContentLength] ] retain];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
[self updateZipDownloaded];
[filesize release];
[connection release];
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[responseData appendData:data];
NSNumber* curLength = [NSNumber numberWithLong:[responseData length] ];
float progress = [curLength floatValue] / [filesize floatValue] ;
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(#"Zip Downloading error");
}
If you want to overcome above error please use below code
NSCharacterSet *setPath = [NSCharacterSet URLPathAllowedCharacterSet];
NSString *strURL = [path stringByAddingPercentEncodingWithAllowedCharacters:setPath];
stringByAddingPercentEncodingWithAllowedCharacters:
Returns a new string made from the receiver by replacing all
characters not in the specified set with percent-encoded characters.
Characters passed to set below methods
(NSCharacterSet *)URLUserAllowedCharacterSet;
(NSCharacterSet *)URLPasswordAllowedCharacterSet;
(NSCharacterSet *)URLHostAllowedCharacterSet;
(NSCharacterSet *)URLPathAllowedCharacterSet;
(NSCharacterSet *)URLQueryAllowedCharacterSet;
(NSCharacterSet *)URLFragmentAllowedCharacterSet;
If you want to go NSURLSession from NSURLConnetion,do the following things
NSURL *URL = [NSURL URLWithString:#"http://example.com"];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *task = [session dataTaskWithRequest:request
completionHandler:
^(NSData *data, NSURLResponse *response, NSError *error) {
// ...
}];
[task resume];
NSURLSession class and related classes provide an API for downloading content via HTTP. This API provides a rich set of delegate methods for supporting authentication and gives your app the ability to perform background downloads when your app is not running or, in iOS, while your app is suspended.
To use the NSURLSession API, your app creates a series of sessions,
each of which coordinates a group of related data transfer tasks. For
example, if you are writing a web browser, your app might create one
session per tab or window. Within each session, your app adds a series
of tasks, each of which represents a request for a specific URL (and
for any follow-on URLs if the original URL returned an HTTP redirect).
Like most networking APIs, the NSURLSession API is highly
asynchronous. If you use the default, system-provided delegate, you
must provide a completion handler block that returns data to your app
when a transfer finishes successfully or with an error. Alternatively,
if you provide your own custom delegate objects, the task objects call
those delegates’ methods with data as it is received from the server
(or, for file downloads, when the transfer is complete).

How to send an asynchronous post request in iOS

I need some help with a LoginViewController.
Basically I have a small app, and I need to post some data to the app and Im new to POST and JSON. If I can get some help and understanding that would be highly appreciated. Below are some requirements im working with. My .m file is labled as LoginViewController. This is what I have so far
-(void)setRequest {
#pragma mark NSURLConnection Delegate Methods
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
// 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 {
// 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
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
// The request has failed for some reason!
// Check the error var
}
-(void)PostRequest{
// Create the request.
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"http://dev.apppartner.com/AppPartnerProgrammerTest/scripts/login.php"]];
// Specify that it will be a POST request
request.HTTPMethod = #"POST";
// This is how we set header fields
[request setValue:#"application/xml; charset=utf-8" forHTTPHeaderField:#"Content-Type"];
// Convert your data and set your request's HTTPBody property
NSString *stringData = #"some data";
NSData *requestBodyData = [stringData dataUsingEncoding:NSUTF8StringEncoding];
request.HTTPBody = requestBodyData;
// Create url connection and fire request
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
}
}
I dont know if I'm even setting this up right. I saw many hTTP posts and what not, but im still confused on how I write this syntax and do I need to add anything additional.
I need to:
Send an asynchronous POST request to "some url"
The POST request must contain the parameters 'username' and 'password'
Will receive a JSON response back with a 'code' and a 'message'
Display the parsed code and message in a UIAlert along with how long the api call took in miliseconds
The only valid login is username: Super password: qwerty
When a login is successful, tapping 'OK' on the UIAlert should bring us back to the MainMenuViewController
I'm assuming the methods inside methods are a typo.
Unless you have a particular reason to implement all those delegate methods, you're probably better off using either
NSURLSessionDataTask *task =
[[NSURLSession sharedSession] dataTaskWithRequest:request
completionHandler:^(NSData *data,
NSURLResponse *response,
NSError *error) {
// Code to run when the response completes...
}];
[task resume];
or the equivalent using NSURLConnection's sendAsynchronousRequest:queue:completionHandler: method if you still need to support iOS 6 and earlier and/or OS X v10.8 and earlier.
But the big thing you're missing is the encoding of the request body. To do that, you'll probably want to use URL encoding and specify the appropriate MIME type for that as shown here:
https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/URLLoadingSystem/WorkingwithURLEncoding/WorkingwithURLEncoding.html
Basically, you construct a string by string concatenation in the form "user=ENCODEDUSERNAME&pass=ENCODEDPASSWORD" where the two encoded values are constructed like this:
NSString *encodedString = (__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes(
kCFAllocatorDefault,
(__bridge NSString *)originalString,
NULL,
CFSTR(":/?#[]#!$&'()*+,;="),
kCFStringEncodingUTF8);
Do not be tempted to use stringByAddingPercentEscapesUsingEncoding: and friends. They will do the wrong thing if your strings contain certain reserved URL characters.
I would suggest that you try working with AFNetworking Library.
You can find the code here.
And a very good tutorial here.
You can do like that for this.
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request addValue:#"YourUsername" forHTTPHeaderField:#"Username"];
[request addValue:#"YourPassword" forHTTPHeaderField:#"Password"];
[NSURLConnection
sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
// TODO: Handle/Manage your response ,Data & errors
}];
-(IBAction)registerclick:(id)sender
{
if (_password.text==_repassword.text)
{
[_errorlbl setHidden:YES];
NSString *requstUrl=[NSString stringWithFormat:#"http://irtech.com/fresery/index.php?route=api/fresery/registerCustomer"];
NSString *postString=[NSString stringWithFormat:#"name=asd&email=sooraj&phonenumber=8111&password=soorajsnr&type=1&facebookid=&image_path="];
// _name.text,_email.text,_mobile.text,_password.text
NSData *returnData=[[NSData alloc]init];
NSMutableURLRequest *request=[[NSMutableURLRequest alloc]initWithURL:[NSURL URLWithString:requstUrl]];
[request setHTTPMethod:#"POST"];
[request setValue:[NSString stringWithFormat:#"%lu", (unsigned long)[postString length]] forHTTPHeaderField:#"Content-length"];
[request setHTTPBody:[postString dataUsingEncoding:NSUTF8StringEncoding]];
returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
resp=[NSJSONSerialization JSONObjectWithData:returnData options:NSJSONReadingMutableContainers error:nil];
c=[[resp valueForKey:#"status" ]objectAtIndex:0];
b=[[resp valueForKey:#"message"]objectAtIndex:0];

Pause a download in objective-c

I'm unsure of what the best approach is for pausing a download. I have seen this question asked on stack over flow before, but doesn't seem to achieve the results I am looking for. For example: I understand inside of the AppDelegate, the - (void)applicationWillResignActive:(UIApplication *)application is called if a phone call comes on the phone for example. It is crucial for my app to successfully download the database to function appropriately. Here's the code I use to download the database:
NSString *urlDb = [NSString stringWithFormat:#"someURl'];
//---Create URL from where DB has to be download-----
NSURL *url = [NSURL URLWithString:urlDb];
NSError *error = nil;
NSData *data = [NSData dataWithContentsOfURL:url options:0 error:&error];
Pausing a download may not be critical for example, AT&T, but folks with Verizon cannot talk and download at the same time. Any help would be greatly appreciated. Thanks!
If you want pause/resume functionality, then you must use either old NSURLConnection, and implement all required delegate methods, or you can use new NSURLSession API.
Here is a basic implementation with NSURLConnection:
#property NSFileHandle *fileHandle;
#property NSURLConnection *connection;
// start download
- (IBAction)downloadButtonPressed
{
NSURL *url = [NSURL URLWithString:#"myUrl"];
NSURLRequest *dataRequest = [NSURLRequest requestWithURL:url];
self.connection = [NSURLConnection connectionWithRequest:dataRequest delegate:self];
[connection start];
}
Implement delegate methods
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
self.fileHandle = [NSFileHandle fileHandleForWritingAtPath:#“pathToYourFile”];
[self.fileHandle seekToEndOfFile];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[self.fileHandle writeData:data];
}
If you want to pause - just cancel connection like this:
[self.connection cancel];
Then you can resume like this:
- (void)resumeDownload
{
NSURL *url = [NSURL URLWithString:#"myUrl"];
NSMutableURLRequest *dataRequest = [NSMutableURLRequest requestWithURL:url];
NSDictionary *fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:pathToYourFile error:&attributesError];
NSNumber *fileSizeNumber = [fileAttributes objectForKey:NSFileSize];
NSString *bytesRangeHeader = [NSString stringWithFormat:#"bytes=%lld-", [fileSizeNumber longLongValue];
[_request setValue:bytesRangeHeader forHTTPHeaderField:#"Range"];
self.connection = [NSURLConnection connectionWithRequest:dataRequest delegate:self];
[connection start];
}

how to send async http post - ios

I have a little problem with my app. I want to send some http request asynchronously to server. I create this method:
- (void)sendHTTPRequest:(NSString *)urlString type:(NSString *)type idNegozio:(NSNumber *)idNegozio {
self.negozi = [[NSMutableArray alloc] init];
NSData *jsonData;
NSString *jsonString;
if ([type isEqualToString:#"shops"]) {
self.reqNeg = YES;
self.reqApp = NO;
...
jsonData = [NSJSONSerialization dataWithJSONObject:jsonDictionary options:0 error:nil];
jsonString = [[NSString alloc]initWithData:jsonData encoding:NSUTF8StringEncoding];
else if ([type isEqualToString:#"appointments"])
{
[self.loadingIconApp startAnimating];
self.reqNeg = NO;
self.reqApp = YES;
...
jsonData = [NSJSONSerialization dataWithJSONObject:jsonDictionary options:0 error:nil];
jsonString = [[NSString alloc]initWithData:jsonData encoding:NSUTF8StringEncoding];
NSString *requestString = [NSString stringWithFormat:urlString];
NSURL *url = [NSURL URLWithString:requestString];
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:30];
[urlRequest setHTTPMethod:#"POST"];
[urlRequest setHTTPBody: jsonData];
NSURLConnection * conn = [[NSURLConnection alloc] initWithRequest:urlRequest delegate:self];
[conn start];
}
and I use this methods for connection:
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
self.responseData = [[NSMutableData alloc] init];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[self.responseData appendData:data];
}
- (NSCachedURLResponse *)connection:(NSURLConnection *)connection
willCacheResponse:(NSCachedURLResponse*)cachedResponse {
return nil;
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
if (self.reqNeg == YES) {
//here use the responseData for my first http request
}
if (self.reqApp == YES) {
//here use the responseData for second http request
}
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
}
but in this way only the first connection works and I can use the responseData. While, If I try to send other http request the method connectionDidFinishLoading doesn't work and other methods too.
Anyone have an idea??
If you want to use the async request one by one you can do that:
- (void)request1 {
NSString *requestString = #"your url here";
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[NSURLConnection sendAsynchronousRequest:[[NSURLRequest alloc]initWithURL:[NSURL URLWithString: requestString]]
queue:queue
completionHandler:
^(NSURLResponse *response, NSData *data, NSError *error) {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
if (!error && httpResponse.statusCode >= 200 && httpResponse.statusCode <300) {
// call the request2 here which is similar to request 1
// your request2 method here
}
}];
}
hope this help you~ thank you~
Your code looks good to me. Here are my ideas:
Are you sure your second NSURLConnection is being created and sent out?
Maybe it's never being sent.
Are you calling your sendHTTPRequest:type:idNegozio: method with a different type while your second connection is still sent out?
You don't have a check at the beginning of the send function to make sure you're not already sending out a connection. Maybe your flags are being switched mid-connection.
The if statements in your didFinish method should probably be combined with an else. Just in case you wanted to fire off an 'app' connection after handling a 'neg' connection you don't accidentally fall through and try to handle the response twice.
Also, you don't have to explicitly call 'start' on an NSURLConnection unless you pass NO to the startImmediately: parameter in the constructor. That shouldn't cause a problem though.

How can I send multiple url request from a NSURLConnection delegate?

This is the logical flow for my application:
At first, when the view controller has finished loading, then a NSURLConnection request can start its execution
The response consists in xml data
After parsing that xml I need to send another NSURLConnection request.
After sending the second request, if the response is ok, I receive other xml data
After parsing the second xml, I have to check some issues between first and second xml data.
So, is it possible to send multiple request? How? I do not need code, you could just explain it.
Thank you in advance.
I do this with the NSURLConnection Making them properties, then checking which one it is:
#property (nonatomic,retain) NSURLConnection *myConnection;
#property (nonatomic,retain) NSURLConnection *mySecondConnection;
then in the delegate:
- (void)connectionDidFinishLoading:(NSURLConnection *)connection{
if (connection == myConnection){
//do something
}
if (connection == mySecondConnection){
// do something else
}
}
You can pass your NSURLRequest to the connection:
self.myConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
There is a third party library available which is a wrapper on CFNetwork is ASIHTTPREQUEST
This Library should do work for you. so that you don't have to write the code from scratch. other alternative is create one class which will be responsible for creating NSURLConnection then sending the request and finally notify to view controller using delegate or notification one data is received .
- (void)viedDidLoad{
[super viewDidLoad];
[self firstRequestMethod];
}
- (void)firstRequestMethod{
NSString *myFirstRequestURL = #"<URL>";
NSURL *webURL = [NSURL URLWithString:myFirstRequestURL];
NSURLRequest *request = [NSURLRequest requestWithURL:webURL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
NSError *error;
NSURLResponse *response;
NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
if(returnData)
{
NSString *returnString = [[NSString alloc] initWithData:returnData encoding:NSASCIIStringEncoding];
//Parse your response here.
//Is desired response obtain call the second Request, as described above
if (TRUE) { //on success
[self secondRequestMethod];
}
}
}
- (void)secondRequestMethod{
NSString *mySecondRequestURL = #"<URL>";
NSURL *webURL = [NSURL URLWithString:mySecondRequestURL];
NSURLRequest *request = [NSURLRequest requestWithURL:webURL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
NSError *error;
NSURLResponse *response;
NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
if(returnData)
{
NSString *returnString = [[NSString alloc] initWithData:returnData encoding:NSASCIIStringEncoding];
//Parse your response here.
//Is desired response obtain call the second Request, as described above
if (TRUE) { //on success
//subsequent calls to other url, same as above
}
}
}
Hope this will help you understand better....

Resources