Timeout interval in synchronous download procedure iOS? - iphone

I have created request as below,
NSURLResponse *response;
NSError *error;
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:JsonURL];
[request setTimeoutInterval:10];
[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
But here time out interval is not working,I checked some questions on stack some said default time out is 75 seconds and some said it's 240 seconds,I am confused here ..
please help me with this.

You are using a synchronous connection. So there will be no calls to a delegate. If you still want to use a synchrous URL request I would recommend the following:
[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
if (nil == response) {
if (error)
NSLog(#"Connection failed! Error - %# %#",
[error localizedDescription],
[[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]);
}
}
If you are want to use the delegate method you have to use an asynchronous request.
Please check the URL Loading System Programming Guide too.

Related

How to execute URL requests from an iOS application?

I want to send the following request to the server. The server already knows what to do with it, but how can I send it?
http://www.********.com/ajax.php?script=logoutUser&username=****
For a synchronous request you would do the following:
NSURL *url = [NSURL URLWithString:#"http://www.********.com/ajax.php?script=logoutUser&username=****"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSURLResponse *response;
NSError *error;
//send it synchronous
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
// check for an error. If there is a network error, you should handle it here.
if(!error)
{
//log response
NSLog(#"Response from server = %#", responseString);
}
Update: for doing an asynchronous request please refere to this example
You can do:
NSString *resp = [NSString stringWithContentsOfURL:url usedEncoding:enc error: &error];

AFNetworking POST to REST webservice

Brief backstory, our previous developer used ASIHTTPRequest to make POST requests and retrieve data from our webservice. For reasons unknown this portion of our app stopped working. Seemed like good enough time to future proof and go with AFNetworking. REST webservice runs on the CakePHP framework.
In short I am not receiving the request response string using AFNetworking.
I know the webservice works because I am able to successfully post data and receive the proper response using curl:
curl -d "data[Model][field0]=field0value&data[Model][field1]=field1value" https://example.com/api/class/function.plist
Per the previous developer's instructions I came up with the following.
#import "AFHTTPRequestOperation.h"
…
- (IBAction)loginButtonPressed {
NSURL *url = [NSURL URLWithString:#"https://example.com/api/class/function.plist"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"POST"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setValue:[usernameTextField text] forHTTPHeaderField:#"data[User][email]"];
[request setValue:[passwordTextField text] forHTTPHeaderField:#"data[User][password]"];
AFHTTPRequestOperation *operation = [[[AFHTTPRequestOperation alloc] initWithRequest:request] autorelease];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"operation hasAcceptableStatusCode: %d", [operation.response statusCode]);
NSLog(#"response string: %# ", operation.responseString);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"error: %#", operation.responseString);
}];
[operation start];
}
output:
operation hasAcceptableStatusCode: 200
response string: a blank plist file
attempted solution 1:
AFNetworking Post Request
the proposed solution uses a function of AFHTTPRequestOperation called operationWithRequest. However, when I attempt to use said solution I get a warning "Class method '+operationWithRequest:completion:' not found (return type defaults to 'id'"
attempted solution 2: NSURLConnection. output: I'm able to print the success log messaged but not the response string.
*update - returns blank plist.
NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url];
NSString *httpBodyData = #"data[User][email]=username#example.com&data[User][password]=awesomepassword";
[httpBodyData dataUsingEncoding:NSUTF8StringEncoding];
[req setHTTPMethod:#"POST"];
[req setHTTPBody:[NSData dataWithContentsOfFile:httpBodyData]];
NSHTTPURLResponse __autoreleasing *response;
NSError __autoreleasing *error;
[NSURLConnection sendSynchronousRequest:req returningResponse:&response error:&error];
// *update - returns blank plist
NSData *responseData = [NSURLConnection sendSynchronousRequest:req returningResponse:nil error:nil];
NSString *str = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
NSLog(#"responseData %#",str);
if (error == nil && response.statusCode == 200) {
// Process response
NSLog(#"success");//returns success code of 200 but blank
NSLog(#"resp %#", response );
} else {
// Process error
NSLog(#"error");
}
These are the essential (stripping out conditions I've made for my own use) lines that ended up satisfying my request to the web service. Thanks for the suggestions #8vius and #mattt !
- (IBAction)loginButtonPressed {
NSURL *baseURL = [NSURL URLWithString:#"https://www.example.com/api/class"];
//build normal NSMutableURLRequest objects
//make sure to setHTTPMethod to "POST".
//from https://github.com/AFNetworking/AFNetworking
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:baseURL];
[httpClient defaultValueForHeader:#"Accept"];
NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:
[usernameTextField text], kUsernameField,
[passwordTextField text], kPasswordField,
nil];
NSMutableURLRequest *request = [httpClient requestWithMethod:#"POST"
path:#"https://www.example.com/api/class/function" parameters:params];
//Add your request object to an AFHTTPRequestOperation
AFHTTPRequestOperation *operation = [[[AFHTTPRequestOperation alloc]
initWithRequest:request] autorelease];
//"Why don't I get JSON / XML / Property List in my HTTP client callbacks?"
//see: https://github.com/AFNetworking/AFNetworking/wiki/AFNetworking-FAQ
//mattt's suggestion http://stackoverflow.com/a/9931815/1004227 -
//-still didn't prevent me from receiving plist data
//[httpClient registerHTTPOperationClass:
// [AFPropertyListParameterEncoding class]];
[httpClient registerHTTPOperationClass:[AFHTTPRequestOperation class]];
[operation setCompletionBlockWithSuccess:
^(AFHTTPRequestOperation *operation,
id responseObject) {
NSString *response = [operation responseString];
NSLog(#"response: [%#]",response);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"error: %#", [operation error]);
}];
//call start on your request operation
[operation start];
[httpClient release];
}
Use AFHTTPClient -postPath:parameters:success:failure:, passing your parameters (nested dictionaries/arrays are fine). If you're expecting a plist back, be sure to have the client register AFPropertyListRequestOperation.
In any case, setValue:forHTTPHeaderField: is not what you want here. HTTP headers are for specifying information about the request itself; data is part of the request body. AFHTTPClient automatically converts parameters into either a query string for GET requests or an HTTP body for POST, et al.

Refactoring my code for asynchronous NSURLConnection

There are problems with using synchronous requests. The problem is that I am not really sure how to refactor the code below to use an asynchronous request to accomplish the following two tasks:
Use a UIActivityIndicatorView subview to notify of active fetching;
Implement a Reachability check before the connection request to ensure that there is an Internet connection and that the host is available, i.e. reachabilityWithHostName:#"wwww.mywebhostingisterrible.com".
Currently I have a Fetcher class with a +(Fetcher *)sharedFetcher singleton that is used in all of my view controllers to fetch data. Currently all data is fetched using the following code:
- (NSString *)stringWithUrl:(NSURL *)url {
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:30];
NSData *urlData;
NSURLResponse *response;
NSError *error;
urlData = [NSURLConnection sendSynchronousRequest:urlRequest
returningResponse:&response
error:&error];
return [[NSString alloc] initWithData:urlData encoding:NSUTF8StringEncoding];
}
A method that fetches looks like this:
-(NSArray *)fetchDogFoodListing {
NSString *urlString = [NSString stringWithFormat:#"%#query/dogFood/%#/%lli/%#/%#",self.connectionUrl,self.queryCriteria.dogFoodName,self.queryCriteria.dogFoodBrandId,self.queryCriteria.dogFoodIngredients,self.queryCriteria.dogFoodBrand];
NSString *json = [self stringWithUrl:[NSURL URLWithString:urlString]];
return [self.factory buildIKDogFoodArrayWithJSON:json];
}
and a call from the UIViewController in -(void)viewDidLoad looks like this:
self.dogFoods = [[IKFetcher sharedFetcher] fetchDogFoodListing];
I have thought about implementing a delegate in this situation but I am very shaky on how delegation ought to work. I'm not even sure which way it should go. Should the Fetcher have a FetcherDelegate that can notify the view controller of when it is done, so the UI can update? Should the view controller have a delegate so that the fetcher can update the view when stuff is done?
I'm sure based on my questions you can see my inexperience with delegation, so I would appreciate any help.
You could do something like this
dispatch_async(queue, ^{
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:30];
NSData *urlData;
NSURLResponse *response;
NSError *error;
urlData = [NSURLConnection sendSynchronousRequest:urlRequest
returningResponse:&response
error:&error];
dispatch_async(dispatch_get_main_queue(), ^{
//.. do stuff with data here...
}
}
or you could just do the sendSynchronousRequest code inside a dispatch_sync if you want the connection to be synchronous, though you should really should be as asynchronous as possible.
you may want to look at the brilliant framework by Mugunth Kumar:
http://blog.mugunthkumar.com/products/ios-framework-introducing-mknetworkkit
I plan on using this for NSURLConnection in my future projects

HTTP POST request not working over 3G

When making the following HTTP POST request:
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"POST"];
NSURLResponse *urlResponse = nil;
NSError *error = nil;
// execute
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&urlResponse error:&error];
if(responseData)
{
//blah
}
I get back a valid response when connected via WiFi, but not when connected over 3G. The responseData object doesn't even get made (0x0) when coming back over 3G.
I get kCFErrorDomainCFNetwork error 303.
The response ought to be 242k of JSON.
Any help would be greatly appreciated.
Thanks.
It seemed that the problem was between the back end system and the mobile networks. Changing the header information to text format only solved the issue.

Google Translate API for iPhone - UTF8 problem in Chinese Translation

I've tested a workable translation API url by:
http://translate.google.com/translate_a/t?client=t&text=%E5%BB%A3%E5%A0%B4&langpair=zh|zh-CN
And it returns the correct result as the following which is in JSON format:
{"sentences":[{"trans":"广场","orig":"廣場","translit":"Guǎngchǎng"}],"src":"zh-CN"}
However, when I try to use this function in XCode, I experienced this problem ...
Here is my code:
NSData *data;
NSString *urlPath = [NSString stringWithFormat:#"/translate_a/t?client=t&text=%#&langpair=zh|zh-CN",qText];
NSURL *url = [[NSURL alloc] initWithScheme:#"http"
host:#"translate.google.com"
path:urlPath];
NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] init] autorelease];
[request setURL:url];
[request setHTTPMethod:#"GET"];
NSURLResponse *response;
NSError *error;
data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; //Problem's here. It returns nil.
NSLog(result);
Initially I guessed it's encoding problem so I tried other encoding as well (NSISOLatin1StringEncoding) , but I got wrong answer: {"sentences":[{"trans":"ã ","orig":"ã ","translit":"Tu¨¯ "}],"src":"zh-CN"}
Does anyone know how to solve this problem? Thank you very much!
Have you tried checking the error object? If an error occurs, this call will just set the error object and continue - it won't crash/throw like a normal error.
Try something like this after the sendSynchronousRequest call:
if (error != nil)
{
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
This should give more details if an error occurred.