NSURLConnection and pointer types bug - objective-c

Here the problem, i'am using a http request, but when i use NSURLConnection to get my xml file and set a NSString *xml variable with that xml file i get a block pointer error if i return it. But if i take NSString *xml and send it to a method it tells me nothing and the xml variable is well set. Also if i return at the end of my method the variable, i get a nil at the parent calling method. How can i fix this because the return of the variable is needed. Thanks for any help, and here is my code :
The error :
incompatible block pointer types sending 'NSString *(^)NSURLResponse *, NSData *, NSError *)'to parameter of type 'void(^)(NSURLResponse *,NSData *, NSError *)'
- (NSString *)restTestRequester: (NSString *)uriRequested serviceUri:(NSString *)sUri parameters:(NSString *)uriParameters technique:(NSString *)requestTechnique {
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
NSString *l_api_key = [prefs stringForKey:#"globalPublicK"];
NSString *l_secret_key = [prefs stringForKey:#"globalSecretK"];
l_uri = [NSString stringWithFormat:#"%#/%#", uriRequested, sUri];
NSMutableURLRequest *theRequest=[NSMutableURLRequest requestWithURL:[NSURL URLWithString:l_uri]
cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
timeoutInterval:60.0];
[theRequest setHTTPMethod:requestTechnique];
[theRequest setValue:#"application/xml" forHTTPHeaderField:#"Accept"];
[theRequest setValue:#"application/x-www-form-unrlencoded" forHTTPHeaderField: #"Content-Type"];
[theRequest setValue:l_api_key forHTTPHeaderField: #"EMApikey"];
[theRequest setValue:[self hmacsha1:l_uri secret:l_secret_key] forHTTPHeaderField: #"EMRequestHash"];
NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
if( theConnection )
{
[NSURLConnection sendAsynchronousRequest:theRequest
queue:[NSOperationQueue mainQueue]
incompatible block pointer types error--> completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
{
here ---->xml = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]
autorelease];
works--->[self myMethod:xml];
doesn't work---> return(xml);
}
];
}
else
{
NSLog(#"theConnection is NULL");
}
[theConnection release];
equals nil variable returned-->return xml;
}

I think that the problem is in async call, U still don't have anything in xml when U trie to return it, your method returns before sendAsynchronousRequest finishes.
USE:
NSData* data=[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSString* xml = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
It will wait until U get the result back.

You have several major problems. For starters, your block executes after your connection finishes. The code after the block executes after the connection STARTS. This means you releasing the connection before it finishes.
Additionally, you are creating NSURLConnection *theConnection, but never using it. When you call -sendAsynchronousRequest:queue:completionHandler: it creates a completely new handler.
The specific error you are getting is because you cannot return a value from the block. The fact that you are trying indicates that you do not have a full grasp of exactly what is happening. There are many good references around the Internet about blocks and asynchronous programming. I suggest you find one.
NSURL *targetURL = [NSURL URLWithString:l_uri];
NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL:targetUrl
cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
timeoutInterval:60.0];
[theRequest setHTTPMethod:requestTechnique];
[theRequest setValue:#"application/xml" forHTTPHeaderField:#"Accept"];
[theRequest setValue:#"application/x-www-form-unrlencoded" forHTTPHeaderField: #"Content-Type"];
[theRequest setValue:l_api_key forHTTPHeaderField: #"EMApikey"];
[theRequest setValue:[self hmacsha1:l_uri secret:l_secret_key] forHTTPHeaderField: #"EMRequestHash"];
[NSURLConnection sendAsynchronousRequest:theRequest
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
{
// Here the connection is complete and the data is usable.
NSString *xml = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
[self myMethod:xml];
[xml release];
}];
// Here the Connection has only been queued and no data is available.

Related

How to send json data in the Http request to POST Method in JSON Parsing

I need to Parse below string to POST method in iOS
"jsonData":{"empId":"cxvd","password":"sfsd"}
But I m getting the error as
Res: Tomcat Error
HTTP Status 400 - Required String parameter 'jsonData' is not present
//------ Method I have used to Parse is ---------- //
+(void) requestToServerForLogin:(NSString*)userName andPassward: (NSString*)password onCompletion:(RequestCompletionHandler) handler
{
NSString *url = [Ip stringByAppendingString:#"login"];
NSString *jsonString = [NSString stringWithFormat:#"\"jsonData\":{\"empId\":\"%#\",\"password\":\"%#\"}",
userName,
password ];
NSURL *nsurl = [NSURL URLWithString:url];
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:nsurl];
[urlRequest setTimeoutInterval:60.0f];
[urlRequest setHTTPMethod:#"POST"];
[urlRequest setValue:#"application/json"
forHTTPHeaderField:#"Content-type"];
NSString *body = jsonString1;
[urlRequest setHTTPBody:[body dataUsingEncoding:NSUTF8StringEncoding]];
NSLog(#"urlRequest :%#",[body dataUsingEncoding:NSUTF8StringEncoding]);
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[NSURLConnection sendAsynchronousRequest:urlRequest
queue:queue
completionHandler:^(NSURLResponse *response,
NSData *data1, NSError *error)
{
NSString *res = [[NSString alloc] initWithData:data1 encoding:NSUTF8StringEncoding];
if(handler) handler(res,error);
}];
}
Thanks in advance
There is way to much code. The substringToIndex and substringFromIndex are wrong, should not be in the code.
Use the literal syntax for the dictionaries:
NSDictionary *jsonDict = #{#"jsonData":#{#"password":password, #"empId":userName}};
NSData* jsonData = [NSJSONSerialization dataWithJSONObject:jsonDict options:0 error:&error];

NSMutableURLRequest returns old values even cachePolicy is NSURLCacheStorageNotAllowed

Im using codes posted here:
connection release method in connectionDidFinishLoading, causes error
now first execute returns didFail log.
second execute; returns old response data.
albeit my (localhost) server is totally offline.
and cachePolicy is NSURLCacheStorageNotAllowed (check the code on the link I posted above)
NSMutableURLRequest *request=
[NSMutableURLRequest requestWithURL:url
cachePolicy:NSURLCacheStorageNotAllowed timeoutInterval:3.0f];
the response data seems cached somewhere and still exists.
but if I use NSURLRequestReloadIgnoringLocalAndRemoteCacheData //which is commented as -not implemented-
not returns old cache.
but if so what is the difference between:
NSURLRequestReloadIgnoringLocalAndRemoteCacheData
and
NSURLCacheStorageNotAllowed
what shall I do ?
NSURLCacheStorageNotAllowed refers to NSCachedURLResponse and is an value of enum NSURLCacheStoragePolicy. Since the cache policy of NSMutableURLRequest is also an enum (NSURLRequestCachePolicy) you just pass wrong int to the static method creating NSMutableURLRequest. In this case NSURLCacheStorageNotAllowed is just 2 which equals to NSURLRequestReturnCacheDataElseLoad - and that is why you get old data.
Try This
NSString *Post = [[NSString alloc] initWithFormat:#"Post Parameters"];
NSURL *Url = [NSURL URLWithString:#"Url"];
NSData *PostData = [Post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *postLength = [NSString stringWithFormat:#"%d", [PostData length]];
NSMutableURLRequest *Request = [[NSMutableURLRequest alloc] init];
[Request setURL:Url];
[Request setHTTPMethod:#"POST"];
[Request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[Request setValue:#"application/json" forHTTPHeaderField:#"Accept"];
[Request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[Request setHTTPBody:PostData];
NSError *error;
NSURLResponse *response;
NSData *Result = [NSURLConnection sendSynchronousRequest:Request returningResponse:&response error:&error];
if (!Result)
{
NSLog(#"Error");
}
else
{
//Parse the result
}

NSURLConnection closes early on GET

I'm working on a method to centralize my URL connections for sending and receiving JSON data from a server. It works with POST, but not GET. I'm using a Google App Engine server and on my computer it'll handle the POST requests and return proper results (and log appropriately), but I get the following error when I try the request with a GET method:
Error Domain=kCFErrorDomainCFNetwork Code=303 "The operation couldn’t be completed. (kCFErrorDomainCFNetwork error 303.)" UserInfo=0xd57e400 {NSErrorFailingURLKey=http://localhost:8080/api/login, NSErrorFailingURLStringKey=http://localhost:8080/api/login}
In addition, the GAE dev server shows a "broken pipe" error, indicating that the client closed the connection before the server was finished sending all data.
Here's the method:
/* Connects to a given URL and sends JSON data via HTTP request and returns the result of the request as a dict */
- (id) sendRequestToModule:(NSString*) module ofType:(NSString*) type function:(NSString*) func params:(NSDictionary*) params {
NSString *str_params = [NSDictionary dictionaryWithObjectsAndKeys:func, #"function", params, #"params", nil];
NSString *str_url = [NSString stringWithFormat:#"%#%#", lds_url, module];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:str_url]];
NSData *data = [[NSString stringWithFormat:#"action=%#", [str_params JSONString]] dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPMethod:type];
[request setHTTPBody:data];
[request setValue:[NSString stringWithFormat:#"%d", [data length]] forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
NSError *error = nil;
NSURLResponse *response = nil;
NSData *result = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSLog(#"Error: %#", error);
NSLog(#"Result: %#", [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding]);
return [result objectFromJSONData];
}
A sample call would be:
NSDictionary *response = [fetcher sendRequestToModule:#"login" ofType:#"GET" function:#"validate_email" params:dict];
Again, this works with a POST but not a GET. How can I fix this?
In my case i was not calling [request setHTTPMethod: #"POST" ]
I think the root cause is you have an invalid URL.
JSON encoding will include things like '{', '}', '[' and ']'. All of these need to be URL encoded before being added to a URL.
NSString *query = [NSString stringWithFormat:#"?action=%#", [str_params JSONString]];
query = [query stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *URL = [NSURL URLWithString:[NSString stringWithFormat:#"%#%#", str_url, query]];
To directly answer your question:
According to CFNetwork Error Codes Reference the error is kCFErrorHTTPParseFailure. This means the client failed to correctly parse the HTTP response.
The reason why is that a GET doesn't include a body. Why would you want to submit JSON in a GET anyways?
If the target api returns data only you pass it in the url params.
If you want to send data and "get" a response use a post and examine the body on return.
Sample Post:
NSError *error;
NSString *urlString = [[NSString alloc] initWithFormat:#"http://%#:%#/XXXX/MVC Controller Method/%#",self.ServerName, self.Port, sessionId ];
NSURL *url = [NSURL URLWithString:[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding ]];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"POST"];
// hydrate the remote object
NSString *returnString = [rdc JSONRepresentation];
NSData *s10 = [returnString dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPBody:s10];
NSURLResponse *theResponse = [[NSURLResponse alloc] init];
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&theResponse error:&error];
NSString *message = [[NSString alloc] initWithFormat: #"nothing"];
if (error) {
message = [[NSString alloc] initWithFormat:#"Error: %#", error];
} else {
message = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
}
NSLog(#"%#", message);
return message;

Implement Timeout in HTTP Post

What is the best way to implement a connection timeout (let's say, 20 seconds) within an HTTP post connection?
My current code is as follows:
-(NSData*) postData: (NSString*) strData
{
//postString is the STRING TO BE POSTED
NSString *postString;
//this is the string to send
postString = #"data=";
postString = [postString stringByAppendingString:strData];
NSURL *url = [NSURL URLWithString:#"MYSERVERHERE"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
NSString *msgLength = [NSString stringWithFormat:#"%d", [postString length]];
//setting prarameters of the POST connection
[request setHTTPMethod:#"POST"];
[request addValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request addValue:msgLength forHTTPHeaderField:#"Content-Length"];
[request addValue:#"en-US" forHTTPHeaderField:#"Content-Language"];
[request setHTTPBody:[postString dataUsingEncoding:NSUTF8StringEncoding]];
[request setTimeoutInterval:10.0];
NSLog(#"%#",postString);
NSURLResponse *response;
NSError *error;
NSLog(#"Starting the send!");
//this sends the information away. everybody wave!
NSData *urlData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSLog(#"Just finished receiving!");
if (&error) //OR TIMEOUT
{
NSLog(#"ERROR!");
NSString *errorString = [NSString stringWithFormat:#"ERROR"];
urlData = [errorString dataUsingEncoding:NSUTF8StringEncoding];
}
return urlData;
}
Obviously the timeout interval is set to 10.0, but nothing seems to happen when those ten seconds hit.
See:
NSMutableURLRequest timeout interval not taken into consideration for POST requests
Apparently timeouts under 240 seconds are ignored. The highest voted answer in that question links to a solution. However, I would simply recommend using the ASIHTTPRequest library instead.
http://allseeing-i.com/ASIHTTPRequest/

get data from url xcode

i am trying to load the data from an online link that works with php. The link returns an xml.
That xml i want to save in the Documents Directory from the iPad.
I am trying this:
NSString *post = #"";
NSData *postData = [post dataUsingEncoding:NSISOLatin1StringEncoding allowLossyConversion:NO];
NSMutableURLRequest *urlRequest = [[[NSMutableURLRequest alloc] init] autorelease];
[urlRequest setURL:[NSURL URLWithString:#"http://www.test.be/tools/xml_nieuwsbrief.php"]];
[urlRequest setHTTPMethod:#"POST"];
[urlRequest setHTTPBody:postData];
NSData *urlData;
NSURLResponse *response;
NSError *error;
urlData = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:&response error:&error];
if(!urlData) {
NSLog(#"No connection!");
}
NSLog(#"Receive:%d bytes",[urlData length]);
NSString *aStr = [[[NSString alloc] initWithData:urlData encoding:NSUTF8StringEncoding]autorelease];
NSLog(#"________%#", aStr);
the string does return - null -, i a have been searching the internet, but does not find anything that can lead me to my problem.
Can someone help me for letting me see what i am doing wrong?
Thanks in advance,
Snowy
I'd check the status code of the response object (change the NSURLResponse object into an NSHTTPURLResponse and you'll have a statusCode property available).
If you are actually getting - null - out of the NSData-response you should probably be looking at the server-side script. Perhaps it is not expecting an empty POST-request?