How to Use Nsurlsessiondatatask in Swift

How to use NSURLSessionDataTask in Swift

It's unclear what you're asking, but I noticed that you have a couple of errors in the code:

  1. You should create your session using NSURLSession(configuration: config)

  2. session.dataTaskWithRequest returns a NSURLSessionDataTask, so there's no need to wrap it inside NSURLSessionDataTask() (a.k.a instantiating a new NSURLSessionDataTask object).

  3. The completion handler is a closure and here's how you create that particular clousure:

    {(data : NSData!, response : NSURLResponse!, error : NSError!) in

    // your code

    }

Here's the updated code:

let url = NSURL(string: "https://itunes.apple.com/search?term=\(searchTerm)&media=software")
let request = NSURLRequest(URL: url)
let config = NSURLSessionConfiguration.defaultSessionConfiguration()
let session = NSURLSession(configuration: config)

let task = session.dataTaskWithRequest(request, completionHandler: {(data, response, error) in

// notice that I can omit the types of data, response and error

// your code

});

// do whatever you need with the task e.g. run
task.resume()

How to use NSURLsession and its delegate methods

YOU CAN DO LIKE THIS:

//GET REQUEST CODE
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
// NSURLSession *s = [NSURLSession sharedSession];
NSURL *url = [NSURL URLWithString:@"PUT_YOUR_URL"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
//
if (data) {
NSHTTPURLResponse * httpResponse = (NSHTTPURLResponse*)response;
NSInteger statusCode = httpResponse.statusCode;
if (statusCode == 200) {
//PERFORM YOUR OPERATIONS
}
}else if (error)
{
NSLog(@"Errorrrrrrr....");
}

}];
[dataTask resume];

How to get data from a Swift NSURLSession?

I'm not sure NSString is the type you want. JSON may be format of the data returned, depending on your URL's functionality. I tried the code provided and got the same issues, but if you treat it as JSON (I used httpbin.org as a dummy URL source) and it worked.

    let task = NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: "http://httpbin.org/get")!, completionHandler: { (data, response, error) -> Void in
do{
let str = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.AllowFragments) as! [String:AnyObject]
print(str)
}
catch {
print("json error: \(error)")
}
})
task.resume()

(thanks for suggested edit @sgthad. the edit is not particularly relevant to the question, but still wanted to update the code to be current.)

Update for Swift 3 syntax

let url = URL(string: "http://httpbin.org/get")!
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
guard let unwrappedData = data else { return }
do {
let str = try JSONSerialization.jsonObject(with: unwrappedData, options: .allowFragments)
print(str)
} catch {
print("json error: \(error)")
}
}
task.resume()

Swift 2 How do I wait for NSURLSessionDataTask to complete before continuing code

The proper way to do this is to add a completion handler

func sendRequest(completion: () -> Void) {
// ...
let task = session.dataTaskWithRequest(request) {
// ...

completion()
}
task.resume()
}

Usage:

let r = Request()
r.sendRequest {
// It's done, do something
}

If you insist on blocking the thread (I hope it's not the main thread), use a semaphore. But remember to signal semaphore whether the request succeeded or failed. I've seen far too many code that forgot to signal the semaphore when the request fail so the app just hung up.

func sendRequest() {
let semaphore = dispatch_semaphore_create(0)

let task = session.dataTaskWithRequest(request) {
// ...
dispatch_semaphore_signal(semaphore)
}
task.resume()
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)
}

Testing NSURLSession resume cannot be sent to abstract instance of class NSURLSessionDataTask

HERE someone rewrote the article and you can test below code in Playground:

import UIKit
import XCTest
import PlaygroundSupport
import Foundation

// Protocol for MOCK/Real
protocol URLSessionProtocol {
typealias DataTaskResult = (Data?, URLResponse?, Error?) -> Void

func dataTask(with request: URLRequest, completionHandler: @escaping DataTaskResult) -> URLSessionDataTaskProtocol
}

protocol URLSessionDataTaskProtocol {
func resume()
}

//MARK: HttpClient Implementation
class HttpClient {

typealias completeClosure = ( _ data: Data?, _ error: Error?)->Void

private let session: URLSessionProtocol

init(session: URLSessionProtocol) {
self.session = session

}

func get( url: URL, callback: @escaping completeClosure ) {
var request = URLRequest(url: url)
request.httpMethod = "GET"
let task = session.dataTask(with: request) { (data, response, error) in
callback(data, error)
}
task.resume()
}

}

//MARK: Conform the protocol
extension URLSession: URLSessionProtocol {
func dataTask(with request: URLRequest, completionHandler: @escaping URLSessionProtocol.DataTaskResult) -> URLSessionDataTaskProtocol {
return dataTask(with: request, completionHandler: completionHandler) as URLSessionDataTask
}
}

extension URLSessionDataTask: URLSessionDataTaskProtocol {}

//MARK: MOCK
class MockURLSession: URLSessionProtocol {

var nextDataTask = MockURLSessionDataTask()
var nextData: Data?
var nextError: Error?

private (set) var lastURL: URL?

func successHttpURLResponse(request: URLRequest) -> URLResponse {
return HTTPURLResponse(url: request.url!, statusCode: 200, httpVersion: "HTTP/1.1", headerFields: nil)!
}

func dataTask(with request: URLRequest, completionHandler: @escaping DataTaskResult) -> URLSessionDataTaskProtocol {
lastURL = request.url

completionHandler(nextData, successHttpURLResponse(request: request), nextError)
return nextDataTask
}

}

class MockURLSessionDataTask: URLSessionDataTaskProtocol {
private (set) var resumeWasCalled = false

func resume() {
resumeWasCalled = true
}
}

//MARK: Test
class HttpClientTests: XCTestCase {

var httpClient: HttpClient!
let session = MockURLSession()

override func setUp() {
super.setUp()
httpClient = HttpClient(session: session)
}

override func tearDown() {
super.tearDown()
}

func test_get_request_with_URL() {

guard let url = URL(string: "http://gojek-contacts-app.herokuapp.com/contacts.json") else {
fatalError("URL can't be empty")
}

httpClient.get(url: url) { (success, response) in
// Return data
}

XCTAssert(session.lastURL == url)

}

func test_get_resume_called() {

let dataTask = MockURLSessionDataTask()
session.nextDataTask = dataTask

guard let url = URL(string: "http://gojek-contacts-app.herokuapp.com/contacts.json") else {
fatalError("URL can't be empty")
}

httpClient.get(url: url) { (success, response) in
// Return data
}

XCTAssert(dataTask.resumeWasCalled)
}

func test_get_should_return_data() {
let expectedData = "{}".data(using: .utf8)

session.nextData = expectedData

var actualData: Data?
httpClient.get(url: URL(string: "http://gojek-contacts-app.herokuapp.com/contacts.json")!) { (data, error) in
actualData = data
}

XCTAssertNotNil(actualData)
}

}

HttpClientTests.defaultTestSuite.run()

How to get data to return from NSURLSessionDataTask in Swift

With the help and suggestion taken from Abizern I finally managed how to write up this block or closure if you want.

So what worked for me in the end:

The GetHomeData function I changed as follows:

private let siteContent:String = "http://www.imoc.co.nz/MobileApp/HomeContent"
// I changed the signiture from my original question
func GetHomeData(completionHandler: ((NSDictionary!) -> Void)?)
{
var url : NSURL! = NSURL(string:siteContent)
var request: NSURLRequest = NSURLRequest(URL:url)
let config = NSURLSessionConfiguration.defaultSessionConfiguration()
let session = NSURLSession(configuration: config)

let task : NSURLSessionDataTask = session.dataTaskWithRequest(request, completionHandler: {(data, response, error) in
var error: AutoreleasingUnsafeMutablePointer<NSError?> = nil

let jsonResult: NSDictionary! = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: error) as? NSDictionary!

// then on complete I call the completionHandler...
completionHandler?(jsonResult?);
});
task.resume()
}

Then I call the function like this:

/*Call to go get home page content*/
func SetHomeContent()
{
homeModel.GetHomeData(self.resultHandler)
}

func resultHandler(jsonResult:NSDictionary!)
{
let siteContent = jsonResult.objectForKey("SiteContent") as NSDictionary
let paraOne = siteContent.objectForKey("HomePageParagraphOne") as String
}


Related Topics



Leave a reply



Submit