How to Get Data to Return from Nsurlsessiondatatask in Swift

How to get data to return from NSURLSessionDataTask

The post completes asynchronously, so your wsClass needs to tell the caller about completion after post is finished. A nice way to do this is to augment the sendData method with a block of code supplied by the caller that should be run upon completion:

Change sendData: to look like this:

// it doesn't return anything, because all it does is launch the post
// but when the post is done, it invokes completion

- (void)sendData:(NSDictionary *)sendDict completion:(void (^)(NSDictionary *))completion {

// the stuff you're already doing

NSURLSessionDataTask *postDataTask = [session dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
// the stuff you're already doing
// now tell the caller that you're done
completion(jsonArray);
}];
}

The caller now looks like this:

// change the UI to say "I'm busy doing the post"
[ws sendData:testDict completion:^(NSDictionary *responseDict) {
NSLog(@"this runs later, after the post completes %@", responseDict);
// change the UI to say "The post is done"
}];

Just a couple of notes about this: (1) I didn't add an error param to the block, you probably should. Check that and invoke the block with either nil and an error, or with the json output and error=nil. (2) Your code assumes that the json result parses as a dictionary. Make sure that's always true before you assume it in code. (3) Class names usually begin with caps.

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
}

NSURLSessionDataTask return data in completion handler, Swift 2.0

In your current function definition type of completionHandler is optional String, it's not a function. If you want completionHandler to be a function that you call when data task finishes, change function definition to func getConfigurationLink(completionHandler: String? -> ()). So here completionHandler is a function that takes an optional String as parameter.

You can read on how to pass a function as a parameter type for another function (that's what you're trying to do here, you're passing completionHandler function to getConfigurationLink and then calling completionHandler when network request completes) here: https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Functions.html#//apple_ref/doc/uid/TP40014097-CH10-ID166

And a little more explanation about compeletionHandlers: https://thatthinginswift.com/completion-handlers/

You can call getConfigurationLink using closure like this:

getConfigurationLink { (str: String?) in
// you can use str here
}

Here is more info on closures: https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Closures.html

How can I get the Data from NSURLSession.sharedSession().dataTaskWithRequest

You can't return data directly from an asynchronous task.

The solution with Swift 2 is to make a completion handler like this:

class PostFOrData {
// the completion closure signature is (NSString) -> ()
func forData(completion: (NSString) -> ()) {
if let url = NSURL(string: "http://210.61.209.194:8088/SmarttvWebServiceTopmsoApi/GetReadlist") {
let request = NSMutableURLRequest( URL: url)
request.HTTPMethod = "POST"
let postString : String = "uid=59"
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
data, response, error in
if let data = data,
jsonString = NSString(data: data, encoding: NSUTF8StringEncoding)
where error == nil {
completion(jsonString)
} else {
print("error=\(error!.localizedDescription)")
}
}
task.resume()
}
}
}

let pfd = PostFOrData()

// you call the method with a trailing closure
pfd.forData { jsonString in
// and here you get the "returned" value from the asynchronous task
print(jsonString)
}

That way, the completion is only called when the asynchronous task is completed. It is a way to "return" the data without actually using return.

Swift 3 version

class PostFOrData {
// the completion closure signature is (String) -> ()
func forData(completion: @escaping (String) -> ()) {
if let url = URL(string: "http://210.61.209.194:8088/SmarttvWebServiceTopmsoApi/GetReadlist") {
var request = URLRequest(url: url)
request.httpMethod = "POST"
let postString : String = "uid=59"
request.httpBody = postString.data(using: String.Encoding.utf8)
let task = URLSession.shared.dataTask(with: request) {
data, response, error in
if let data = data, let jsonString = String(data: data, encoding: String.Encoding.utf8), error == nil {
completion(jsonString)
} else {
print("error=\(error!.localizedDescription)")
}
}
task.resume()
}
}
}

let pfd = PostFOrData()

// you call the method with a trailing closure
pfd.forData { jsonString in
// and here you get the "returned" value from the asynchronous task
print(jsonString)
}

Swift - Return data from NSURLSession when sending POST request

Your post function might be like:

func post(completionHandler: (response: String) -> ()) { your code }

And in the response part:

let responseString = NSString(data: data, encoding: NSUTF8StringEncoding)
completionHandler(response: responseString)

Finally, you can call your post method like:

post( {(response: String) -> () in
println("response = \(response)")})

How to get data from blocks using NSURLSession?

-(void)getJsonResponse:(NSString *)urlStr success:(void (^)(NSDictionary *responseDict))success failure:(void(^)(NSError* error))failure
{
NSURLSession *session = [NSURLSession sharedSession];
NSURL *url = [NSURL URLWithString:urlStr];

// Asynchronously API is hit here
NSURLSessionDataTask *dataTask = [session dataTaskWithURL:url
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSLog(@"%@",data);
if (error)
failure(error);
else {
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSLog(@"%@",json);
success(json);
}
}];
[dataTask resume]; // Executed First
}

call this:

[self getJsonResponse:@"Enter your url here" success:^(NSDictionary *responseDict) {   
NSLog(@"%@",responseDict);
} failure:^(NSError *error) {
// error handling here ...
}];


Related Topics



Leave a reply



Submit