I'm trying to use NSURLSession with a DataTask and a Delegate but I can't find a way to convert the data obtained by the didReceiveData method into a string.
This is the code that I'm using, the problem that I'm experiencing is that I get some data but when I try to convert this data into a string I get nil, while the expected result would be the source of the page that I've requested.
class ViewController: UIViewController, NSURLSessionDataDelegate {
var session:NSURLSession?
var data = NSMutableData()
override func viewDidLoad() {
super.viewDidLoad()
let sessionConfiguration = NSURLSessionConfiguration.defaultSessionConfiguration()
session = NSURLSession(configuration: sessionConfiguration, delegate: self, delegateQueue: NSOperationQueue.mainQueue())
session!.dataTaskWithRequest(NSURLRequest(URL: NSURL(string: "http://www.google.com")!)).resume()
}
func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?){
var str = NSString(data: NSData(data: self.data), encoding: NSUTF8StringEncoding)
println(data) // IT PRINTS DATA CONTENT
println(str) // IT PRINTS nil :(
}
func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData data: NSData){
self.data.appendData(data)
}
Most probably the received string data is not UTF8 encoded. Try NSASCIIStringEncoding.
Related
URLSession data task block is not calling when the app is in background and it stuck at dataTask with request.
When I open the app the block gets called. By the way I'm using https request.
This is my code:
let request = NSMutableURLRequest(url: URL(string: url as String)!,
cachePolicy: .reloadIgnoringCacheData,
timeoutInterval:20)
request.httpMethod = method as String
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
let session = URLSession.shared
let data = params.data(using: String.Encoding.utf8.rawValue)
request.httpBody = data
session.dataTask(with: request as URLRequest,completionHandler:
{(data, response, error) -> Void in
if error == nil
{
do {
let result = try JSONSerialization.jsonObject(with: data!, options:
JSONSerialization.ReadingOptions.mutableContainers)
print(result)
completionHandler(result as AnyObject?,nil)
}
catch let JSONError as NSError{
completionHandler(nil,JSONError.localizedDescription as NSString?)
}
}
else{
completionHandler(nil,error!.localizedDescription as NSString?)
}
}).resume()
Working perfectly when the app is in active state. Is there anything wrong in my code. please point me
If you want downloads to progress after your app is no longer in foreground, you have to use background session. The basic constraints of background sessions are outlined in Downloading Files in Background, and are essentially:
Use delegate-based URLSession with background URLSessionConfiguration.
Use upload and download tasks only, with no completion handlers.
In iOS, Implement application(_:handleEventsForBackgroundURLSession:completionHandler:) app delegate, saving the completion handler and starting your background session.
Implement urlSessionDidFinishEvents(forBackgroundURLSession:) in your URLSessionDelegate, calling that saved completion handler to let OS know you're done processing the background request completion.
So, pulling that together:
func startRequest(for urlString: String, method: String, parameters: String) {
let url = URL(string: urlString)!
var request = URLRequest(url: url, cachePolicy: .reloadIgnoringCacheData, timeoutInterval: 20)
request.httpMethod = method
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.httpBody = parameters.data(using: .utf8)
BackgroundSession.shared.start(request)
}
Where
class BackgroundSession: NSObject {
static let shared = BackgroundSession()
static let identifier = "com.domain.app.bg"
private var session: URLSession!
#if !os(macOS)
var savedCompletionHandler: (() -> Void)?
#endif
private override init() {
super.init()
let configuration = URLSessionConfiguration.background(withIdentifier: BackgroundSession.identifier)
session = URLSession(configuration: configuration, delegate: self, delegateQueue: nil)
}
func start(_ request: URLRequest) {
session.downloadTask(with: request).resume()
}
}
extension BackgroundSession: URLSessionDelegate {
#if !os(macOS)
func urlSessionDidFinishEvents(forBackgroundURLSession session: URLSession) {
DispatchQueue.main.async {
self.savedCompletionHandler?()
self.savedCompletionHandler = nil
}
}
#endif
}
extension BackgroundSession: URLSessionTaskDelegate {
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
if let error = error {
// handle failure here
print("\(error.localizedDescription)")
}
}
}
extension BackgroundSession: URLSessionDownloadDelegate {
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
do {
let data = try Data(contentsOf: location)
let json = try JSONSerialization.jsonObject(with: data)
print("\(json)")
// do something with json
} catch {
print("\(error.localizedDescription)")
}
}
}
And the iOS app delegate does:
func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: #escaping () -> Void) {
BackgroundSession.shared.savedCompletionHandler = completionHandler
}
Or simply start a BackgroundTask
func send(...) {
let backgroundTaskID = UIApplication.shared.beginBackgroundTask(expirationHandler: nil)
let session = URLSession(configuration: .default)
// ... after all the main logic, when you finish:
DispatchQueue.main.async {
completion(result)
UIApplication.shared.endBackgroundTask(backgroundTaskID)
}
}
You need a background session. The URLSessionDataTask which as per Apple's documentation doesn't support background downloads.
Create a URLSessionDownloadTask and use its delegate method it should work.
Follow this link
[URLSessionDownloadTask setDownloadTaskDidWriteDataBlock:^(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, int64_t bytesWritten, int64_t totalBytesWritten, int64_t totalBytesExpectedToWrite) {
CGFloat percentDone = (double)(totalBytesWritten)/(double)totalBytesExpectedToWrite;
[SVProgressHUD showWithStatus:[NSString stringWithFormat:#"%.2f%%",percentDone*100]];
}];
[downloadTask resume];
// Apply as shown in picture
/*********************/
I'm currently connecting to a D-Link Camera successfully through iOS and receiving a stream of images. I need to do the same with audio stream, however I receive raw data and have been facing difficulties in playing the data stream. Below a sample code to show the idea briefly
import UIKit
import AVKit
import MediaPlayer
class ViewController: UIViewController, NSURLSessionDataDelegate{
var audioBuffer = AudioBuffer()
var audioData = NSMutableData()
var player:AVAudioPlayer?
var task:NSURLSessionDataTask?
override func viewDidLoad() {
super.viewDidLoad()
downloadImage()
}
func downloadImage()
{
let url:NSURL = NSURL(string: "http://197.162.158.4:1090/audio/ACAS.cgi")!
let config = NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier("download_session")
let userPasswordString = "admin:admin"
let userPasswordData = userPasswordString.dataUsingEncoding(NSUTF8StringEncoding)
let base64EncodedCredential = userPasswordData!.base64EncodedStringWithOptions([])
let authString = "Basic \(base64EncodedCredential)"
config.HTTPAdditionalHeaders = ["Authorization" : authString]
let request:NSMutableURLRequest = NSMutableURLRequest(URL: url)
let session:NSURLSession = NSURLSession(configuration: config, delegate: self, delegateQueue: NSOperationQueue.mainQueue())
task = session.dataTaskWithRequest(request)
task?.resume()
}
//MARK: NSURLSessionDownloadDelegate
func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData data: NSData) {
audioData.appendData(data)
print(audioData.length)
if audioData.length > 700000
{
//Need to carry out something like this
/* player = try? AVAudioPlayer(data: audioData, fileTypeHint: AVFileTypeCoreAudioFormat)
player?.play()
audioData = NSMutableData()*/
}
}
func URLSession(session: NSURLSession, didReceiveChallenge challenge: NSURLAuthenticationChallenge, completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential?) -> Void) {
}
func URLSession(session: NSURLSession, didBecomeInvalidWithError error: NSError?) {
print(error?.localizedDescription)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
I'm trying to implement this tutorial which implements a custom NSURLProtocol with NSURLConnection.
https://www.raywenderlich.com/76735/using-nsurlprotocol-swift
It works as expected, but now that NSURLConnection is deprecated in iOS9, I'm trying to convert it to NSURLSession.
Unfortunatly it didn't work.
I'm loading a website in uiwebview, if I use NSURLConnection it loads and everything work as expected, all http requests from the webview is captured, but not when using NSURLSession.
Any help is appreciated.
here is my code
import UIKit
class MyProtocol: NSURLProtocol, NSURLSessionDataDelegate, NSURLSessionTaskDelegate, NSURLSessionDelegate {
//var connection: NSURLConnection!
var mutableData: NSMutableData!
var response: NSURLResponse!
var dataSession: NSURLSessionDataTask!
override class func canInitWithRequest(request: NSURLRequest) -> Bool {
if NSURLProtocol.propertyForKey("MyURLProtocolHandledKey", inRequest: request) != nil {
return false
}
return true
}
override class func canonicalRequestForRequest(request: NSURLRequest) -> NSURLRequest {
return request
}
override class func requestIsCacheEquivalent(aRequest: NSURLRequest,
toRequest bRequest: NSURLRequest) -> Bool {
return super.requestIsCacheEquivalent(aRequest, toRequest:bRequest)
}
override func startLoading() {
let newRequest = self.request.mutableCopy() as! NSMutableURLRequest
NSURLProtocol.setProperty(true, forKey: "MyURLProtocolHandledKey", inRequest: newRequest)
self.dataSession = NSURLSession.sharedSession().dataTaskWithRequest(newRequest)
dataSession.resume()
self.mutableData = NSMutableData()
}
override func stopLoading() {
print("Data task stop")
self.dataSession.cancel()
self.mutableData = nil
}
func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveResponse response: NSURLResponse, completionHandler: (NSURLSessionResponseDisposition) -> Void) {
self.response = response
self.mutableData = NSMutableData()
print(mutableData)
}
func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData data: NSData) {
self.client?.URLProtocol(self, didLoadData: data)
self.mutableData.appendData(data)
}
func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?) {
if (error == nil)
{
self.client!.URLProtocolDidFinishLoading(self)
self.saveCachedResponse()
}
else
{
self.client?.URLProtocol(self, didFailWithError: error!)
}
}
func saveCachedResponse () {
let timeStamp = NSDate()
let urlString = self.request.URL?.absoluteString
let dataString = NSString(data: self.mutableData, encoding: NSUTF8StringEncoding) as NSString?
print("TiemStamp:\(timeStamp)\nURL: \(urlString)\n\nDATA:\(dataString)\n\n")
}
}
I've solved it.
Here is the code if anyone needs it.
import Foundation
class MyProtocol1: NSURLProtocol, NSURLSessionDataDelegate, NSURLSessionTaskDelegate
{
private var dataTask:NSURLSessionDataTask?
private var urlResponse:NSURLResponse?
private var receivedData:NSMutableData?
class var CustomKey:String {
return "myCustomKey"
}
// MARK: NSURLProtocol
override class func canInitWithRequest(request: NSURLRequest) -> Bool {
if (NSURLProtocol.propertyForKey(MyProtocol1.CustomKey, inRequest: request) != nil) {
return false
}
return true
}
override class func canonicalRequestForRequest(request: NSURLRequest) -> NSURLRequest {
return request
}
override func startLoading() {
let newRequest = self.request.mutableCopy() as! NSMutableURLRequest
NSURLProtocol.setProperty("true", forKey: MyProtocol1.CustomKey, inRequest: newRequest)
let defaultConfigObj = NSURLSessionConfiguration.defaultSessionConfiguration()
let defaultSession = NSURLSession(configuration: defaultConfigObj, delegate: self, delegateQueue: nil)
self.dataTask = defaultSession.dataTaskWithRequest(newRequest)
self.dataTask!.resume()
}
override func stopLoading() {
self.dataTask?.cancel()
self.dataTask = nil
self.receivedData = nil
self.urlResponse = nil
}
// MARK: NSURLSessionDataDelegate
func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask,
didReceiveResponse response: NSURLResponse,
completionHandler: (NSURLSessionResponseDisposition) -> Void) {
self.client?.URLProtocol(self, didReceiveResponse: response, cacheStoragePolicy: .NotAllowed)
self.urlResponse = response
self.receivedData = NSMutableData()
completionHandler(.Allow)
}
func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData data: NSData) {
self.client?.URLProtocol(self, didLoadData: data)
self.receivedData?.appendData(data)
}
// MARK: NSURLSessionTaskDelegate
func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?) {
if error != nil && error!.code != NSURLErrorCancelled {
self.client?.URLProtocol(self, didFailWithError: error!)
} else {
saveCachedResponse()
self.client?.URLProtocolDidFinishLoading(self)
}
}
// MARK: Private methods
/**
Do whatever with the data here
*/
func saveCachedResponse () {
let timeStamp = NSDate()
let urlString = self.request.URL?.absoluteString
let dataString = NSString(data: self.receivedData!, encoding: NSUTF8StringEncoding) as NSString?
print("TimeStamp:\(timeStamp)\nURL: \(urlString)\n\nDATA:\(dataString)\n\n")
}
}
Swift 3 version:
// CustomURLProtocol.swift
class CustomURLProtocol: URLProtocol, URLSessionDataDelegate, URLSessionTaskDelegate {
private var dataTask: URLSessionDataTask?
private var urlResponse: URLResponse?
private var receivedData: NSMutableData?
class var CustomHeaderSet: String {
return "CustomHeaderSet"
}
// MARK: NSURLProtocol
override class func canInit(with request: URLRequest) -> Bool {
guard let host = request.url?.host, host == "your domain.com" else {
return false
}
if (URLProtocol.property(forKey: CustomURLProtocol.CustomHeaderSet, in: request as URLRequest) != nil) {
return false
}
return true
}
override class func canonicalRequest(for request: URLRequest) -> URLRequest {
return request
}
override func startLoading() {
let mutableRequest = NSMutableURLRequest.init(url: self.request.url!, cachePolicy: NSURLRequest.CachePolicy.useProtocolCachePolicy, timeoutInterval: 240.0)//self.request as! NSMutableURLRequest
//Add User Agent
var userAgentValueString = "myApp"
mutableRequest.setValue(userAgentValueString, forHTTPHeaderField: "User-Agent")
print(mutableRequest.allHTTPHeaderFields ?? "")
URLProtocol.setProperty("true", forKey: CustomURLProtocol.CustomHeaderSet, in: mutableRequest)
let defaultConfigObj = URLSessionConfiguration.default
let defaultSession = URLSession(configuration: defaultConfigObj, delegate: self, delegateQueue: nil)
self.dataTask = defaultSession.dataTask(with: mutableRequest as URLRequest)
self.dataTask!.resume()
}
override func stopLoading() {
self.dataTask?.cancel()
self.dataTask = nil
self.receivedData = nil
self.urlResponse = nil
}
// MARK: NSURLSessionDataDelegate
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask,
didReceive response: URLResponse,
completionHandler: #escaping (URLSession.ResponseDisposition) -> Void) {
self.client?.urlProtocol(self, didReceive: response, cacheStoragePolicy: .notAllowed)
self.urlResponse = response
self.receivedData = NSMutableData()
completionHandler(.allow)
}
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
self.client?.urlProtocol(self, didLoad: data as Data)
self.receivedData?.append(data as Data)
}
// MARK: NSURLSessionTaskDelegate
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
if error != nil { //&& error.code != NSURLErrorCancelled {
self.client?.urlProtocol(self, didFailWithError: error!)
} else {
//saveCachedResponse()
self.client?.urlProtocolDidFinishLoading(self)
}
}
}
The problem you are having with your code is that you are using the the NSURLSession.sharedSession to contain your data task. By using the shared session, you are not able to change the session delegate so none of your delegate routines are going to be invoked.
You will need to create a custom session with your protocol established as the delegate for the session. Then, when asked to start loading you can create a data task in that session.
From the documentation of URLSession:
Important
The session object keeps a strong reference to the delegate until your app exits or explicitly invalidates the session. If you don’t invalidate the session, your app leaks memory until it exits.
Also:
Note
Be careful to not create more sessions than you need. For example, if you have several parts of your app that need a similarly configured session, create one session and share it among them.
So I would move the creation of the URLSession from the startLoading method to the URLProtocol subclass initializer:
class MyURLProtocol: URLProtocol, URLSessionDataDelegate,URLSessionTaskDelegate {
override init(request: URLRequest, cachedResponse: CachedURLResponse?, client: URLProtocolClient?) {
super.init(request: request, cachedResponse: cachedResponse, client: client)
defaultSession = URLSession(configuration: .default, delegate: self, delegateQueue: nil)
}
private var defaultSession: URLSession?
I am fetching data using NSURLSession but I don't know how to get the data back once the download is complete my code :
class ViewController: UIViewController,NSURLSessionDelegate,NSURLSessionDataDelegate{
#IBOutlet var imageView: UIImageView!
#IBOutlet weak var progress: UIProgressView!
var buffer:NSMutableData = NSMutableData()
var session:NSURLSession?
var dataTask:NSURLSessionDataTask?
let url = NSURL(string:"https://initiate.alphacoders.com/download/wallpaper/566046/images7/jpg/37100/1353" )!
var expectedContentLength = 0
var downloadedImage = UIImage()
var downloadedData = NSData()
override func viewDidLoad() {
super.viewDidLoad()
progress.progress = 0.0
let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
let manqueue = NSOperationQueue.mainQueue()
session = NSURLSession(configuration: configuration, delegate:self, delegateQueue: manqueue)
dataTask = session?.dataTaskWithRequest(NSURLRequest(URL: url))
dataTask?.resume()
// Do any additional setup after loading the view, typically from a nib.
}
func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveResponse response: NSURLResponse, completionHandler: (NSURLSessionResponseDisposition) -> Void) {
//here you can get full lenth of your content
expectedContentLength = Int(response.expectedContentLength)
print(expectedContentLength)
completionHandler(NSURLSessionResponseDisposition.Allow)
}
func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData data: NSData) {
if progress.progress > 0.99 {
downloadedImage = UIImage(data: data , scale: 1)!
}
buffer.appendData(data)
print("checking")
let percentageDownloaded = Float(buffer.length) / Float(expectedContentLength)
progress.progress = percentageDownloaded
}
func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?) {
//use buffer here.Download is done
progress.progress = 1.0// download 100% complete
imageView.image = downloadedImage
}
}
I tried to get the data from func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData but at didReceiveData my file is not yet fully downloaded and i don't know how to get the data from didCompleteWithError function , am new in swift and still figuring out things here ,
If anybody knows here what I am missing or what should I do then please tell me, any guidance will be so appreciated and helpful.
- URLSession:downloadTask:didFinishDownloadingToURL:
Is something you are missing.
Called to inform the delegate that a download task has finished downloading.
This method gives you a file URL for the temporary file (The third parameter). Because the file is temporary, you must either open the file for reading or move it to a permanent location in your app’s sandbox container directory before returning from this delegate method.
Find more here.
EDIT 1: To check the progress override following method:
- URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:
EDIT 2: Okay I see now. Make following changes and see if it works?:
Let your class conform NSURLSessionDownloadDelegate
Change dataTask = session?.dataTaskWithRequest(NSURLRequest(URL: url)) to dataTask = session?.downloadTaskWithURL(NSURLRequest(URL: url))
That should make you download the file.
I am making a basic "hello world" iOS app. I have an ubuntu server in the cloud which I want to query from the iOS app. I understand that the server needs to be secure, ie, needs to be accessed via https request, and the certificate on the server needs to be "trusted".
Right now what I am trying to do is override this requirement. I have a self-signed certificate that is working for https on my server. When I make the request with the iOS app, it gives me some errors about NSURLErrorFailingURLPeerTrustErrorKey and even one line returned saying: NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?.
I know this is a common issue and there are many threads on this site about how to deal with it. I tried a piece of code from this post. I added this piece to my code:
func URLSession(session: NSURLSession, task: NSURLSessionTask, didReceiveChallenge challenge: NSURLAuthenticationChallenge, completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential?) -> Void) {
if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust{
let credential = NSURLCredential(forTrust: challenge.protectionSpace.serverTrust!)
completionHandler(NSURLSessionAuthChallengeDisposition.UseCredential,credential);
}
}
My entire ViewController code is here:
import UIKit
class ViewController: UIViewController, UITextFieldDelegate, NSURLSessionDelegate {
// MARK: Properties
#IBOutlet weak var nameTextField: UITextField!
#IBOutlet weak var mealNameLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Handle the text field’s user input through delegate callbacks.
nameTextField.delegate = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: UITextFieldDelegate
func textFieldShouldReturn(textField: UITextField) -> Bool {
// Hide the keyboard.
textField.resignFirstResponder()
return true
}
func textFieldDidEndEditing(textField: UITextField) {
mealNameLabel.text = nameTextField.text
}
// MARK: Actions
#IBAction func setDefaultLabelText(sender: UIButton) {
mealNameLabel.text = "Default Text"
post_request()
}
func post_request(){
let request = NSMutableURLRequest(URL: NSURL(string: "https://54.164.XXX.XX/post_script.php")!)
request.HTTPMethod = "POST"
let postString = "id=13&name=Jack"
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
data, response, error in
if error != nil {
print("error=\(error)")
return
}
print("response = \(response)")
let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding)
print("responseString = \(responseString)")
}
task.resume()
}
func URLSession(session: NSURLSession, task: NSURLSessionTask, didReceiveChallenge challenge: NSURLAuthenticationChallenge, completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential?) -> Void) {
if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust{
let credential = NSURLCredential(forTrust: challenge.protectionSpace.serverTrust!)
completionHandler(NSURLSessionAuthChallengeDisposition.UseCredential,credential);
}
}
}
It looks like the idea is to pick up the challenge event from the connection, and tell it that "yes I want to proceed". But that piece of code does not seem to be getting called. The post request gets sent, but I receive the error messages about the untrusted certificate. Can someone help me fix my code so that I can accept this certificate from my server?
You need to make your ViewController NSURLSessionDelegate to receive the callbacks and set the session's delegate to be your controller, like this:
let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
let session = NSURLSession(configuration: configuration, delegate: self, delegateQueue: nil)
...
let task = session.dataTaskWithRequest(request) { data, response, error in
}
task.resume()
You cannot use the shared session to get those delegate methods. You must instantiate a new NSURLSession and declare yourself as the delegate.
// Delegate methods won't be callend
let task = NSURLSession.sharedSession()...
// Use this to get delegate calls
let task = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration(),
delegate: self,
delegateQueue: /* make a queue */)...
With iOS 9, you will also need to look into NSAppTransportSecurity and adding those keys to your plist. These are needed in iOS 9 to allow SSL connections.