swift - Implementing completion handlers for backgroundSession.uploadTask -


i have (almost) implemented urlsessiondelegate, urlsessiontaskdelegate, , urlsessiondatadelegate can upload objects in background. i'm not sure how implement completion handlers, can delete object sent, when server returns statuscode=200

i start uploadtask this

let configuration = urlsessionconfiguration.background(withidentifier: "com.example.myobject\(myobject.id)") let backgroundsession = urlsession(configuration: configuration,                                     delegate: customdelegate.sharedinstance,                                     delegatequeue: nil) let url: nsurl = nsurl(string: "https://www.myurl.com")! let urlrequest = nsmutableurlrequest(url: url url)  urlrequest.httpmethod = "post" urlrequest.setvalue("multipart/form-data; boundary=\(boundary)", forhttpheaderfield: "content-type")  let uploadtask = backgroundsession.uploadtask(with: urlrequest urlrequest, fromfile: path)  uploadtask.resume() 

i tried adding closure initialization of uploadtask xcode displayed error not possible.

i have custom class customdelegate:

class customdelegate : nsobject, urlsessiondelegate, urlsessiontaskdelegate, urlsessiondatadelegate {  static var sharedinstance = customdelegate()  func urlsession(_ session: urlsession, datatask: urlsessiondatatask, didreceive data: data) {     print("\(session.configuration.identifier!) received data: \(data)")     {         let parseddata = try jsonserialization.jsonobject(with: data, options: .allowfragments) as! [string:any]         let status = parseddata["status"] as! nsdictionary         let statuscode = status["httpcode"] as! int          switch statuscode {         case 200:             //         case 400:             //         case 401:             //         case 403:             //         default:             //         }     }     catch {         print("error parsing response")     } } } 

it implements other functions delegates.

what want somehow know upload done can update ui , database feel hard (maybe impossible?) within customdelegate.

if you're interested in detecting completion of request, simplest approach use closure:

class customdelegate : nsobject, urlsessiondelegate, urlsessiontaskdelegate, urlsessiondatadelegate {      static var sharedinstance = customdelegate()     var uploaddidfinish: ((urlsessiontask, error?) -> void)?      func urlsession(_ session: urlsession, task: urlsessiontask, didcompletewitherror error: error?) {         dispatchqueue.main.async {             uploaddidfinish?(task, error)         }     }  } 

then view controller set closure before initiating request, e.g.

customdelegate.sharedinstance.uploaddidfinish = { [weak self] task, error in     // update ui completion here }  // start request here 

if want update ui multiple situations (e.g. not uploads finish, progress uploads sent), theoretically set multiple closures (one completion, 1 progress), you'd adopt own delegate-protocol pattern. (personally, i'd rename customdelegate uploadmanager avoid confusion who's delegate what, that's you.)

for example might do:

protocol uploaddelegate: class {     func didcomplete(session: urlsession, task: urlsessiontask, error: error?)     func didsendbodydata(session: urlsession, task: urlsessiontask, bytessent: int64, totalbytessent: int64, totalbytesexpectedtosend: int64) } 

then, in network request manager (your customdelegate implementation), define delegate property:

weak var delegate: uploaddelegate? 

in appropriate urlsession delegate methods, you'd call custom delegate methods pass along information view controller:

func urlsession(_ session: urlsession, task: urlsessiontask, didcompletewitherror error: error?) {     // whatever want here      dispatchqueue.main.async {         delegate?.didcomplete(session: session, task: task, didcompletewitherror: error)     } }  func urlsession(_ session: urlsession, task: urlsessiontask, didsendbodydata bytessent: int64, totalbytessent: int64, totalbytesexpectedtosend: int64) {     // whatever want here      dispatchqueue.main.async {         delegate?.didsendbodydata(session: session, task: task, bytessent: bytessent, totalbytessent: totalbytessent, totalbytesexpectedtosend: totalbytesexpectedtosend)     } } 

then, you'd declare view controller conform new protocol , implement these methods:

class viewcontroller: uiviewcontroller, uploaddelegate {     ...     func startrequests() {         customdelegate.sharedinstance.delegate = self          // initiate request(s)     }      func didcomplete(session: urlsession, task: urlsessiontask, error: error?) {         // update ui here     }      func didsendbodydata(session: urlsession, task: urlsessiontask, bytessent: int64, totalbytessent: int64, totalbytesexpectedtosend: int64) {          // update ui here     } } 

now, might update uploaddelegate protocol capture model information , pass parameter methods, too, illustrates basic idea.


some minor observations:

  1. when creating session, should excise nsurl , nsmutableurlrequest types code, e.g.:

    let url = url(string: "https://www.myurl.com")! var urlrequest = urlrequest(url: url)  urlrequest.httpmethod = "post" urlrequest.setvalue("multipart/form-data; boundary=\(boundary)", forhttpheaderfield: "content-type")  let uploadtask = backgroundsession.uploadtask(with: urlrequest, fromfile: path)  uploadtask.resume() 
  2. you looking statuscode in didreceivedata. should doing in didreceiveresponse. also, status code urlresponse.

  3. you parsing response in didreceivedata. generally, should in didcompletewitherror (just in case takes multiple calls didreceivedata receive entire response).

  4. i don't know myobject.id is, identifier you've chosen, "com.example.myobject\(myobject.id)", suspect:

    • are creating new urlsession instance each object? want 1 of requests.

    • when app suspended/jettisoned while upload continues in background, when app restarted, have reliable way of reinstantiating same session objects?
       

    generally you'd want single upload session of uploads, , name should consistent. i'm not saying can't way have, seems it's going problematic recreating sessions without going through work. it's you.

    all of i'd make sure test background uploading process works if app terminated , restarted in background when uploads finish. feels incomplete/fragile, i'm jumping incorrect conclusions , you've got working , didn't sharing details (e.g. app delegate's handleeventsforbackgroundurlsession) sake of brevity (which appreciated).


Comments

Popular posts from this blog

account - Script error login visual studio DefaultLogin_PCore.js -

xcode - CocoaPod Storyboard error: -