Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSURLSession didCompleteWithError: how to determine what task it is?

I have a class that conform to the NSURLSession delegates for downloading data and have an issue when more than one service is called when finished they call the method func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?), the results are parsed and handled here to be returned to the correct view controller.

How do I know from what session or task the results are so I can call the correct view controller?

import Foundation


class Support{

// MARK - Properties
var ID: Int!
var SoftekID: String!
var Subject: String!
var LastUpdate: String!
var LastUpdatedBy: String!
var Priority: Int!
var Impact: Int!
var SupportType: String!
var Importance: Int!


// MARK: General
init() {
    self.ID = 0
    self.SoftekID = ""
    self.Subject = ""
    self.LastUpdate = ""
    self.LastUpdatedBy = ""
    self.Priority = 0
    self.Impact = 0
    self.SupportType = ""
    self.Importance = 0
}

func getSupportTickets(){
let sp = SuppportProvider()
    sp.getSupportTickets()
}
}

class SuppportProvider: NSObject, NSURLSessionDelegate,      NSURLSessionDataDelegate, NSURLSessionTaskDelegate{

// MARK: - Properties
var mData: NSMutableData?
var session: NSURLSession!

override init(){
    super.init()
    prepareConnection()
}

// MARK: - Methods
func prepareConnection(){

    session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration(), delegate: self, delegateQueue:nil)
}

func getSupportTickets(){
    var request = NSMutableURLRequest(URL: NSURL(string: "http://10.0.58.137/ISOWeb.UI/api/CSMobile/GetSupportTickets?PageNumber=0&PagingSize=10&TicketStatus=Priority")!,
        cachePolicy: NSURLRequestCachePolicy.UseProtocolCachePolicy,
        timeoutInterval: 20.0)

    let task =  session.dataTaskWithRequest(request)

    mData = NSMutableData()
    task.resume()
}

func getHelpInformation(){
    var request = NSMutableURLRequest(URL: NSURL(string: "http://10.0.58.137/ISOWeb.UI/api/CSMobile/GetHelpInformation")!,
        cachePolicy: NSURLRequestCachePolicy.UseProtocolCachePolicy,
        timeoutInterval: 20.0)

    let task = session.dataTaskWithRequest(request)

    mData = NSMutableData()
    task.resume()
}

func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveResponse response: NSURLResponse, completionHandler: (NSURLSessionResponseDisposition) -> Void) {

    mData!.length = 0
    completionHandler(NSURLSessionResponseDisposition.Allow)
}

func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData data: NSData) {

    mData!.appendData(data)
}

func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?) {

    if error != nil{
        println("An error has occured completing the request")
    }else{

        //Result for method: getSupportTickets
        var value = NSString(bytes: mData!.mutableBytes, length: mData!.length, encoding: NSUTF8StringEncoding)

        var jError: NSError?

        if let JSONResult: Array<NSDictionary> = NSJSONSerialization.JSONObjectWithData(mData!, options: NSJSONReadingOptions.AllowFragments, error: &jError) as? Array<NSDictionary> {

            if JSONResult.count > 0 {

               var arr = Array<Support>()

                for dict in JSONResult{

                    let item = Support()

                    if (dict["ID"] as? Int != nil) {
                        item.ID = dict["ID"] as! Int
                    }else {
                        item.ID = 0
                    }

                    if (dict["SoftekID"] as? String != nil) {
                        item.SoftekID = dict["SoftekID"] as! String
                    }else {
                        item.SoftekID = ""
                    }

                    if (dict["Subject"] as? String != nil) {
                        item.Subject = dict["Subject"] as! String
                    }else {
                        item.Subject = ""
                    }

                    if (dict["LastUpdate"] as? String != nil) {
                          item.LastUpdate = dict["LastUpdate"] as! String
                    }else {
                        item.LastUpdate = ""
                    }

                    if (dict["LastUpdatedBy"] as? String != nil) {
                         item.LastUpdatedBy = dict["LastUpdatedBy"] as! String
                    }else {
                        item.LastUpdatedBy = ""
                    }

                    if (dict["Priority"] as? Int != nil) {
                         item.Priority = dict["Priority"] as! Int
                    }else {
                         item.Priority = 0
                    }

                    if (dict["Impact"] as? Int != nil) {
                        item.Impact = dict["Impact"] as! Int
                    }else {
                        item.Impact = 0
                    }

                    if (dict["SupportType"] as? String != nil) {
                         item.SupportType = dict["SupportType"] as! String
                    }else {
                        item.SupportType = ""
                    }

                    if (dict["Importance"] as? Int != nil) {
                        item.Importance = dict["Importance"] as! Int
                    }else {
                        item.Importance = 0
                    }

                    arr.append(item)
                }
            }
        }

        //Result for method: getHelpInformation
        //How to know to which task holds the result?
    }
}

}

UPDATE

import Foundation

class CSSupport{

// MARK - Properties
var ID: Int!
var SoftekID: String!
var Subject: String!
var LastUpdate: String!
var LastUpdatedBy: String!
var Priority: Int!
var Impact: Int!
var SupportType: String!
var Importance: Int!


// MARK: General
init() {
    self.ID = 0
    self.SoftekID = ""
    self.Subject = ""
    self.LastUpdate = ""
    self.LastUpdatedBy = ""
    self.Priority = 0
    self.Impact = 0
    self.SupportType = ""
    self.Importance = 0
}
}

class Support:NSObject, NSURLSessionDelegate, NSURLSessionDataDelegate, NSURLSessionTaskDelegate{

// MARK: - Properties
var mData: NSMutableData?
var session: NSURLSession!

 override init(){
    super.init()
    var configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
    session = NSURLSession(configuration:configuration, delegate: self, delegateQueue:nil)
}

// MARK: - Methods
func getSupportTickets(){
    var request = NSMutableURLRequest(URL: NSURL(string: "http://10.0.58.137/ISOWeb.UI/api/CSMobile/GetSupportTickets?PageNumber=0&PagingSize=10&TicketStatus=Priority")!,
        cachePolicy: NSURLRequestCachePolicy.UseProtocolCachePolicy,
        timeoutInterval: 20.0)

    let task =  session.dataTaskWithRequest(request)

    mData = NSMutableData()
    task.resume()
}

func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveResponse response: NSURLResponse, completionHandler: (NSURLSessionResponseDisposition) -> Void) {

    mData!.length = 0
    completionHandler(NSURLSessionResponseDisposition.Allow)
}

func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData data: NSData) {

    mData!.appendData(data)
}

func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?) {

    if error != nil{
        println("An error has occured completing the request")
    }else{

         var value = NSString(bytes: mData!.mutableBytes, length: mData!.length, encoding: NSUTF8StringEncoding)
         var jError: NSError?

        switch task.taskIdentifier {
        case 1:
            if let JSONResult: Array<NSDictionary> = NSJSONSerialization.JSONObjectWithData(mData!, options: NSJSONReadingOptions.AllowFragments, error: &jError) as? Array<NSDictionary> {

                if JSONResult.count > 0 {

                    var arr = Array<CSSupport>()

                    for dict in JSONResult{

                        let item = CSSupport()

                        if (dict["ID"] as? Int != nil) {
                            item.ID = dict["ID"] as! Int
                        }else {
                            item.ID = 0
                        }

                        if (dict["SoftekID"] as? String != nil) {
                            item.SoftekID = dict["SoftekID"] as! String
                        }else {
                            item.SoftekID = ""
                        }

                        if (dict["Subject"] as? String != nil) {
                            item.Subject = dict["Subject"] as! String
                        }else {
                            item.Subject = ""
                        }

                        if (dict["LastUpdate"] as? String != nil) {
                            item.LastUpdate = dict["LastUpdate"] as! String
                        }else {
                            item.LastUpdate = ""
                        }

                        if (dict["LastUpdatedBy"] as? String != nil) {
                            item.LastUpdatedBy = dict["LastUpdatedBy"] as! String
                        }else {
                            item.LastUpdatedBy = ""
                        }

                        if (dict["Priority"] as? Int != nil) {
                            item.Priority = dict["Priority"] as! Int
                        }else {
                            item.Priority = 0
                        }

                        if (dict["Impact"] as? Int != nil) {
                            item.Impact = dict["Impact"] as! Int
                        }else {
                            item.Impact = 0
                        }

                        if (dict["SupportType"] as? String != nil) {
                            item.SupportType = dict["SupportType"] as! String
                        }else {
                            item.SupportType = ""
                        }

                        if (dict["Importance"] as? Int != nil) {
                            item.Importance = dict["Importance"] as! Int
                        }else {
                            item.Importance = 0
                        }

                        arr.append(item)
                    }
                }
            }
            break

        case 2:

            break

        default:
            println("No task was found.")
            break
        }
    }
}

}
like image 575
Angie Avatar asked Aug 03 '15 15:08

Angie


3 Answers

Yes, the lack of any sort of customizable storage is kind of annoying, particularly because the identifier is only unique on a per-session basis. There are a few ways to handle this:

  • If you're using background sessions or a mixture of foreground and background sesions, I think the best thing you can do is a two-level lookup, in which you associate a mutable dictionary with each session and look up the session first, then look up the task by its identifier within the per-session dictionary:

    • For background sessions, provide an identifier to use as the key in the top-level mutable dictionary.
    • For other sessions, use the session object itself as the key in the top-level mutable dictionary.
  • If you're using only foreground tasks (not in a background session, that is), you should be able to just use the tasks as dictionary keys and look up additional data related to the tasks.

I think that both of those techniques should work correctly. You might also be able to use associated objects on the task to store additional data (so long as you aren't working with background sessions).

One thing you definitely can't do (I already filed a bug about this) is subclass NSURLRequest and store additional data there, because NSURLSession returns its own copy of the NSURLRequest (rather than your custom subclass) when you ask for currentRequest, and returns a seemingly random instance of your subclass (unrelated to the actual original request) when you ask for orginalRequest.

It's amazing how much effort everyone has to expend creating external dictionaries to work around the lack of a simple refCon object property on each task and on each session. It is definitely worth filing a bug to ask for that feature.

like image 195
dgatwood Avatar answered Nov 15 '22 04:11

dgatwood


Why not using your own custom string identifier in taskDescription which is a member of NSURLSessionTask ?

like image 23
Jerome Avatar answered Nov 15 '22 03:11

Jerome


Maybe taskIdentifier property could help you: https://developer.apple.com/library/ios/documentation/Foundation/Reference/NSURLSessionTask_class/index.html#//apple_ref/occ/instp/NSURLSessionTask/taskIdentifier

like image 39
4esterUA Avatar answered Nov 15 '22 05:11

4esterUA