ios - Is There A Neat Way to Attach a Completion Block to an NSURLSessionDataDelegate Callback in Swift? -
ok, here's deal:
i have url call i'm making in swift app, sort of so:
/*! @brief tests given root server url validity @discussion here, append "/client_interface/serverinfo.xml" given uri, , test validity. @param inuriasastring contains string, uri. @param incompletionblock completion block supplied caller. called upon receipt of data. @returns implicitly unwrapped optional string. given uri, "cleaned up." */ class func testrootserveruri(inuriasastring:string, incompletionblock:requestcompletionblock!) -> string! { // first, trim off trailing slashes. var ret:string! = inuriasastring.stringbytrimmingcharactersinset(nscharacterset(charactersinstring: "/")) // next, make string entirely lowercase. ret = ret.lowercasestring // add "http://" if necessary. if(!ret.beginswith ("http")) { ret = "http://" + ret } // uri test. let testuristring = ret + "/client_interface/serverinfo.xml" #if debug print("testing \(testuristring).") #endif let url:nsurl! = nsurl(string: testuristring) // can't have url in play. bad. if(nil == self.urlextradata[testuristring]) { // assuming have completion block , uri, try version server (determine validity). if((nil != incompletionblock) && (nil != ret)) { // store completion block recall later. self.urlextradata.updatevalue(incompletionblock, forkey: testuristring) let datatask:nsurlsessiontask = bmltadminappdelegate.connectionsession.datataskwithurl(url)! datatask.resume() } } else { ret = nil } return ret }
actually, that, it's function i'm using (a static class function).
the problematic line one:
self.urlextradata.updatevalue(incompletionblock, forkey: testuristring)
"urlextradata" dictionary declare earlier:
/*! dictionary of callbacks open requests. keys on url called. @discussion hate pulling crap this, it's clumsy , thread-unfriendly. unfortunately, there doesn't seem choice, there's no way attach refcon url task. */ static var urlextradata:dictionary<string,requestcompletionblock!>! = nil
and assign here:
// set empty dictionary url refcon data. bmltadminappdelegate.urlextradata = dictionary<string,requestcompletionblock!>()
the completion block typedef here:
/*! @brief definition testrootserveruri completion block. @discussion routine called upon completion of url connection. when connection ends (either or not), routine called. if successful, indata parameter non-nil. if failed, parameter nil. @param indata data returned. */ typealias requestcompletionblock = (indata: nsdata!)->void
the session setup here:
bmltadminappdelegate.connectionsession = nsurlsession(configuration: config, delegate:self, delegatequeue: nsoperationqueue.mainqueue())
the delegate response handler is here:
/*! @brief called when task receives data. @param session nsurlsession controls task. @param datatask task responsible callback. @param data data returned. */ func urlsession(session: nsurlsession, datatask: nsurlsessiondatatask, didreceivedata data: nsdata) { let url = datatask.currentrequest?.url // don't squat if there no callback in our table. if(nil != bmltadminappdelegate.urlextradata.indexforkey((url?.absolutestring)!)) { // fetch stored comnpletion block our dictionary. let callback:requestcompletionblock! = bmltadminappdelegate.urlextradata[(url?.absolutestring)!] // if 1 provided (always check), call it. if(nil != callback) { bmltadminappdelegate.urlextradata.removevalueforkey((url?.absolutestring)!) // remove callback dictionary. callback(indata: data) } } }
i think using dictionary hold second callback nasty, smelly hack. however, have found no way attach refcon task. i'd rather attach secondary completion block directly task, opposed using separate dictionary.
i'd love told methodology bad, long given better.
any takers?
thanks!
what i've done in past create sort of transaction object. set download manager (as singleton) create array of transaction objects. make transaction object delegate of url session (actually predates nsurlsession - did nsurlconnection, idea same.)
the transaction object has completion block parameter. when download completes, transaction object invokes it's completion block, , notifies download manager singleton it's done , ready cleaned up.
Comments
Post a Comment