Deprecated: 'sendAsynchronousRequest:queue:completionHandler:' in iOS9 - ios

I have my own class to make http calls but now in iOS9 this method is deprecated:
[NSURLConnetion sendAsynchronousRequest:queue:completionHandler:]
I'm trying to test the new one
[NSURLSession dataTaskWithRequest:completionHandler:]
but Xcode give an error because it doesn't found this method.
Xcode compiler warning with deprecated line:
'sendAsynchronousRequest:queue:completionHandler:' is deprecated: first deprecated in iOS 9.0 - Use [NSURLSession dataTaskWithRequest:completionHandler:] (see NSURLSession.h
Error with new method:
No known class method for selector 'dataTaskWithRequest:completionHandler:'
Method:
-(void)placeGetRequest:(NSString *)action withHandler:(void (^)(NSURLResponse *response, NSData *data, NSError *error))ourBlock {
NSString *url = [NSString stringWithFormat:#"%#/%#", URL_API, action];
NSURL *urlUsers = [NSURL URLWithString:url];
NSURLRequest *request = [NSURLRequest requestWithURL:urlUsers];
//[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:ourBlock];
[NSURLSession dataTaskWithRequest:request completionHandler:ourBlock];
}
Any idea?

dataTaskWithRequest:completionHandler: is an instance method, not a class method. You have to either configure a new session or use the shared one:
[[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:ourBlock] resume];

[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data,NSURLResponse *response,NSError *error)
{
// Block Body
}];

If you are using the AFNetworking library, you can use a session and then set up to support requests in the background. Using this approach I solved two problems:
1) AFNetworking method is not deprecated
2) the request processing will be done even if the application between the state background
I hope it helps to similar problems. This is an alternative.
-(void) pingSomeWebSite {
NSString* url = URL_WEBSITE; // defines your URL to PING
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setHTTPMethod:#"GET"];
[request setURL:[NSURL URLWithString:url]];
request.timeoutInterval = DEFAULT_TIMEOUT; // defines your time in seconds
NSTimeInterval today = [[NSDate date] timeIntervalSince1970];
NSString *identifier = [NSString stringWithFormat:#"%f", today];
NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:identifier];
sessionConfig.timeoutIntervalForResource = DEFAULT_TIMEOUT_INTERVAL; // interval max to background
__block AFURLSessionManager *manager = [[AFURLSessionManager alloc]
initWithSessionConfiguration:
sessionConfig];
NSURLSessionTask *checkTask = [manager dataTaskWithRequest:request
completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
NSLog(#"- Ping to - %#", URL_WEBSITE);
NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;
dispatch_async(dispatch_get_main_queue(), ^(){
[manager invalidateSessionCancelingTasks:YES];
// LOGIC FOR RESPONSE CODE HERE
});
}];
[checkTask resume];
}

let task = NSURLSession.sharedSession().dataTaskWithRequest(request){ data, response, error in
// Code
}
task.resume()

Related

NSURLSession send token back to server not working with ios10

I am trying to use NSURLSession, I had successfully received token from server, now I have to used that Token to get further details...
I had tried below code to get user data..
but I am getting httpResponse code: 500
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
NSString *authValue = [arrTokenData valueForKey:#"Token"];
//Configure session with common header fields
NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
sessionConfiguration.HTTPAdditionalHeaders = #{#"bearer": authValue};
NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration];
NSString *url = #"http://test.myserver.am/api/mobile/LookUps/getuserdata";
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];
NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
if (!error) {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
if (httpResponse.statusCode == 200)
{
NSDictionary *jsonData = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers|NSJSONReadingAllowFragments error:nil];
//Process the data
}
}
}];
[task resume];
I am using iOS 10 , above code is not working, also I have tried several ways but no any success...
I have tried stackoverflow solution but this is also not working out for me...
Please help me out...

How to make a PUT request in NSURLSession?

I want to make a PUT request to a URL, but when the output shows status code as 405, which means the request to the URL is something other than put.
NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate: nil delegateQueue: [NSOperationQueue mainQueue]];
NSURL * url = [NSURL URLWithString:#"http://httpbin.org/put"];
NSMutableURLRequest *request =[[NSMutableURLRequest alloc]initWithURL:url];
NSData *postbody = [#"name=testname&suggestion=testing123" dataUsingEncoding:NSUTF8StringEncoding];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
request.HTTPMethod = #"PUT";
[request setHTTPBody:postbody];
NSURLSessionDataTask * dataTask = [defaultSession dataTaskWithURL:url
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if(error == nil)
{
[request setHTTPBody:data];
NSLog(#"Response = %#",response);
}
}];
[dataTask resume];
Can someone point out where i am going wrong, i have been reading a lot about this issue since the last couple of hours, but i am not able to figure it out. Kindly do not mark this as duplicate since the previous op did not add body which is not the case with my code. Also the URL mentioned accepts any data as body, so i guess what i set the data to is irrelevant.
EDIT (ANSWER):
After banging my head from yesterday, one of my senior helped me solve the issue, hope this will help someone. The data task needs to be supplied with the request object and not with the URL, this was the reason it always showed 'GET' in Charles web debugging tool. The code should be as follows:
NSURLSessionDataTask * dataTask = [defaultSession dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
// code
}];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
request.HTTPMethod = #"PUT";

How to wait for completion of NSURLSession?

I have a method that downloads a binary from a server and returns it.
But before the NSURLSession completes, my function is returning the value, so it's coming to be nil each time.
How can I wait till the download is complete and then return the binary?
Try this -
NSURLSession *delegateFreeSession = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate: nil delegateQueue: [NSOperationQueue mainQueue]];
[[delegateFreeSession dataTaskWithURL: [NSURL URLWithString: #"http://www.example.com/"]
completionHandler:^(NSData *data, NSURLResponse *response,
NSError *error) {
NSLog(#"Got response %# with error %#.\n", response, error);
NSLog(#"DATA:\n%#\nEND DATA\n",
[[NSString alloc] initWithData: data
encoding: NSUTF8StringEncoding]);
[self loadDataToView:data]; // << your custom method inside the MyViewControllerClass
}] resume];
Your method should take a callback as an argument. Once the NSURLSession completion handler gets the object you need, you call that callback with the data (or an NSError object if you got an error back from the server)
You can't 'wait' for execution to continue after you get the data. By definition, such network operations are handled asynchronously, hence the need for a callback.
Update: sample code below
- (void)getFeed:(NSDictionary*)parameters fromURL:(NSString*)url withCallback:(void (^)(NSData *data, NSURLResponse *response, NSError *error))callback {
NSURL*newsfeedUrl = [NSURL URLWithString:url];
NSMutableURLRequest *newsfeedRequest = [NSMutableURLRequest requestWithURL:newsfeedUrl];
[newsfeedRequest addValue:#"XMLHTTPRequest" forHTTPHeaderField:#"X-Requested-With"];
newsfeedRequest.HTTPMethod = #"GET";
NSURLSessionDataTask *downloadNeewsfeedDataTask = [instance.session dataTaskWithRequest:newsfeedRequest completionHandler:^(NSData*data, NSURLResponse*response, NSError*error) {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*) response;
NSLog(#"statusCode %ld", (long)httpResponse.statusCode);
//Do something here in your completion handler and call your callback function when ready (either with the data you expected, or with an error object. Alternatively, you can outright refrain from adding a completion handler block and simply put your callback argument as the completion handler (they must have the same signature).
callback(data, response, error);
}];
[downloadNeewsfeedDataTask resume];
}
Here is the example of completion handler for NSURLSession.
-(void) httpPostWithCustomDelegate{
NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate: nil delegateQueue: [NSOperationQueue mainQueue]];
NSURL * url = [NSURL URLWithString:#"http://hayageek.com/examples/jquery/ajax-post/ajax-post.php"];
NSMutableURLRequest * urlRequest = [NSMutableURLRequest requestWithURL:url];
NSString * params =#"name=Ravi&loc=India&age=31&submit=true";
[urlRequest setHTTPMethod:#"POST"];
[urlRequest setHTTPBody:[params dataUsingEncoding:NSUTF8StringEncoding]];
NSURLSessionDataTask * dataTask =[defaultSession dataTaskWithRequest:urlRequest
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSLog(#"Response:%# %#\n", response, error);
if(error == nil)
{
NSString * text = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
NSLog(#"Data = %#",text);
}
}];
[dataTask resume];
}
Here is good tutorial for NSURLSession.

NSURLSessionDownloadTask and retrying

I am using the following code to download a file from the web. How do i structure the code (using blocks) such that, if it fails, it will be retried with a max of retrycount. Here is the code that i am using to download the file.
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
NSURL *myURL = [NSURL URLWithString:#"urlstring"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:myURL];
[request setValue:token forHTTPHeaderField:#"Authorization"];
NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request progress:nil destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) {
NSURL *directoryURL = [NSURL fileURLWithPath:NSTemporaryDirectory()];
return [directoryURL URLByAppendingPathComponent:fileName];
} completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) {
//check here if error then retry using block ?
if (!error)
{
//do something with the file
}
else
{
//retry download ??
}
}
}];
[downloadTask resume];
You could create a retryCount instance variable and set it to however many times you want to retry the network call. Then you could put all your networking code in a method with a custom completion handler. Your completion handler could be a block that takes a BOOL as a parameter and returns void. Then, in your networking code, create a local BOOL variable and set it to YES or NO based on whether the network call succeeded or failed. You'll run the completion handler argument within your networking code. Then the block (completion handler) that you send as a parameter to the method can "see" whether the local variable in your method was set to YES or NO. If it was YES, the network call succeeded, so do nothing. If it was NO, the network call failed, so check retryCount--if it's > 0, call the networking method again and decrement retryCount.
UPDATE
This should give you a rough idea...
typedef void (^CustomCompletionHandler)(BOOL); // Create your CustomCompletionHandler type
- (void)getDataAndCallCompletionHandler:(CustomCompletionHandler *)completionHandler {
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
NSURL *myURL = [NSURL URLWithString:#"urlstring"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:myURL];
[request setValue:token forHTTPHeaderField:#"Authorization"];
NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request progress:nil destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) {
BOOL success = NO; // Create local variable to keep track of whether network call succeeded or failed
NSURL *directoryURL = [NSURL fileURLWithPath:NSTemporaryDirectory()];
return [directoryURL URLByAppendingPathComponent:fileName];
} completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) {
//check here if error then retry using block ?
if (!error)
{
success = YES;
//do something with the file
}
else
{
success = NO;
//retry download ??
}
}
// Get main queue and call completionHandler and pass success:
// completionHandler(success)
}];
[downloadTask resume];
}
You would call this method by doing something like...
[self getDataAndCallCompletionHandler:^(BOOL success) {
// If success == true {
// Do whatever you need to
// } else {
// Check retryCount
// If you need to, call getDataAndCallCompletionHandler: again
// }
}];

Add user information in request

Since ASIHTTPRequest is deprecated, I am migrating my code to use NSURLSession based server communication. Currently, I am using NSDictionary "userInfo" property of ASIHTTPRequest to send additional user information. The description of "userInfo" in ASIHTTPRequest documentation is "Custom user information associated with the request (not sent to the server)".
After the request is processed, I re-fetch this "userInfo" object from the request object and take action accordingly.
My ASIHTTPRequest code example is
Request:
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:#"http://www.google.com"];
[request setDelegate:self];
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:1] forKey:#"requestCount"];
[request setUserInfo:userInfo];
I want to achieve same functionality through NSURLSession, how can I do this?
NSURLSession code example:
NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate: nil delegateQueue: self.queue];
NSMutableURLRequest * urlRequest = [NSMutableURLRequest requestWithURL:url];
[urlRequest setTimeoutInterval:timeOutSeconds];
NSURLSessionDataTask * dataTask =[defaultSession dataTaskWithRequest:urlRequest
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSLog(#"Response:%# %#\n", response, error);
if(error == nil)
{
NSString * text = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
NSLog(#"Data = %#",text);
}
}
}];
[dataTask resume];
Because you are using completion handler so you can use block variable, try below code:
NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate: nil delegateQueue: self.queue];
NSMutableURLRequest * urlRequest = [NSMutableURLRequest requestWithURL:url];
[urlRequest setTimeoutInterval:timeOutSeconds];
__block NSDictionary *userInfo = [NSDictionary dictionaryWithObjectAndKeys...........];**
NSURLSessionDataTask * dataTask =[defaultSession dataTaskWithRequest:urlRequest
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSLog(#"Response:%# %#\n", response, error);
NSLog(#"UserInfo: %#", userInfo);
if(error == nil)
{
NSString * text = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
NSLog(#"Data = %#",text);
}
}
}];
[dataTask resume];
The cleanest way to go is to subclass NSURLRequest and add the desired property - be it tag, or userInfo and use it the same way you are used to with ASIHTTP framework.

Resources