swiftcompletionhandlernsurlsessiontask

How to get data to return from NSURLSessionDataTask in Swift


I have this same question as was asked and answered here: How to get data to return from NSURLSessionDataTask

The difference: How can I do this in Swift? I do not know Objective C at all so trying to interpret that answer is proving a bit futile for me..

So given the code below I have a FirstViewController which will call my HomeModel class to go and get the data using a NSURLSession call. Once the call is complete I want return the data to the FirstViewController so that I may go and set it in the view.

FirstViewController class looks like:

import UIKit
class FirstViewController: UIViewController
{
    let homeModel = HomeModel()

    override func viewDidLoad()
    {
       super.viewDidLoad()

       // Go load the home page content
       SetHomeContent()
    }

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

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

      //TODO find a way to get result here... and set it to the textView
  }
}

HomeModel class looks like:

 import Foundation
 class HomeModel
 {

    private let siteContent:String = "http://www.imoc.co.nz/MobileApp/HomeContent"

   func GetHomeData()
   {
      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!

      // At this stage I want the jsonResult to be returned to the FirstViewController
    });

    // do whatever you need with the task
    task.resume()
}

I guess I want either a way to pass in a completion handler from the original all or something similar to C# 5 using async tasks to await the result..

Any help appreciated..


Solution

  • 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
    }