swift - Healthkit HKAnchoredObjectQuery in iOS 9 not returning HKDeletedObject -


i excited learn apple added tracking of deletes in healthkit in ios 9. set test project try out. unfortunately, while can new data fine, not getting deleted objects in callbacks.

i have functioning hkanchoredobjectquery tracks hkqueryanchor , gives me new hksamples whenever add bloodglucose quantity healthkit via health app. when delete same quantity , re-run app hkdeletedobject empty. add , delete @ same time. seems no matter do, hkdeletedobject array empty. additions work fine (only getting added samples since last anchor).

here code. 2 files. recreate project make new swift project, give healthkit entitlement, , copy these in. (note: when run it, 1 update each run if make changes in healthkit have stop , restart app test callbacks.)

this healthkit client:

// //  hkclient.swift //  hktest  import uikit import healthkit  class hkclient : nsobject {      var issharingenabled: bool = false     let healthkitstore:hkhealthstore? = hkhealthstore()     let glucosetype : hkobjecttype = hkobjecttype.quantitytypeforidentifier(hkquantitytypeidentifierbloodglucose)!      override init(){         super.init()     }      func requestglucosepermissions(authorizationcompleted: (success: bool, error: nserror?)->void) {          let datatypestoread : set<hkobjecttype> = [ glucosetype ]          if(!hkhealthstore.ishealthdataavailable())         {             // let error = nserror(domain: "com.test.healthkit", code: 2, userinfo: [nslocalizeddescriptionkey: "healthkit not available on device"])             self.issharingenabled = false             return         }          self.healthkitstore?.requestauthorizationtosharetypes(nil, readtypes: datatypestoread){(success, error) -> void in             self.issharingenabled = true             authorizationcompleted(success: success, error: error)         }     }      func getglucosesinceanchor(anchor:hkqueryanchor?, maxresults:uint, callback: ((source: hkclient, added: [string]?, deleted: [string]?, newanchor: hkqueryanchor?, error: nserror?)->void)!){         let queryenddate = nsdate(timeintervalsincenow: nstimeinterval(60.0 * 60.0 * 24))         let querystartdate = nsdate.distantpast()         let sampletype: hksampletype = glucosetype as! hksampletype         let predicate: nspredicate = hkanchoredobjectquery.predicateforsampleswithstartdate(querystartdate, enddate: queryenddate, options: hkqueryoptions.none)         var hkanchor: hkqueryanchor;          if(anchor != nil){             hkanchor = anchor!         } else {             hkanchor = hkqueryanchor(fromvalue: int(hkanchoredobjectquerynoanchor))         }          let onanchorqueryresults : ((hkanchoredobjectquery, [hksample]?, [hkdeletedobject]?, hkqueryanchor?, nserror?) -> void)! = {             (query:hkanchoredobjectquery, addedobjects:[hksample]?, deletedobjects:[hkdeletedobject]?, newanchor:hkqueryanchor?, nserror:nserror?) -> void in              var added = [string]()             var deleted = [string]()              if (addedobjects?.count > 0){                 obj in addedobjects! {                     let quant = obj as? hkquantitysample                     if(quant?.uuid.uuidstring != nil){                         let val = double( (quant?.quantity.doublevalueforunit(hkunit(fromstring: "mg/dl")))! )                         let msg : string = (quant?.uuid.uuidstring)! + " " + string(val)                         added.append(msg)                     }                 }             }              if (deletedobjects?.count > 0){                 del in deletedobjects! {                     let value : string = del.uuid.uuidstring                     deleted.append(value)                 }             }              if(callback != nil){                 callback(source:self, added: added, deleted: deleted, newanchor: newanchor, error: nserror)             }         }          let anchoredquery = hkanchoredobjectquery(type: sampletype, predicate: predicate, anchor: hkanchor, limit: int(maxresults), resultshandler: onanchorqueryresults)         healthkitstore?.executequery(anchoredquery)     }      let anchorkey = "hkclientanchorkey"     func getanchor() -> hkqueryanchor? {         let encoded = nsuserdefaults.standarduserdefaults().dataforkey(anchorkey)         if(encoded == nil){             return nil         }         let anchor = nskeyedunarchiver.unarchiveobjectwithdata(encoded!) as? hkqueryanchor         return anchor     }      func saveanchor(anchor : hkqueryanchor) {         let encoded = nskeyedarchiver.archiveddatawithrootobject(anchor)         nsuserdefaults.standarduserdefaults().setvalue(encoded, forkey: anchorkey)         nsuserdefaults.standarduserdefaults().synchronize()     } } 

this view:

// //  viewcontroller.swift //  hktest  import uikit import healthkit  class viewcontroller: uiviewcontroller {     let debuglabel = uilabel(frame: cgrect(x: 10,y: 20,width: 350,height: 600))      override func viewdidload() {         super.viewdidload()          self.view = uiview();         self.view.backgroundcolor = uicolor.whitecolor()           debuglabel.textalignment = nstextalignment.center         debuglabel.textcolor = uicolor.blackcolor()         debuglabel.linebreakmode = nslinebreakmode.bywordwrapping         debuglabel.numberoflines = 0         self.view.addsubview(debuglabel)          let hk = hkclient()         hk.requestglucosepermissions(){             (success, error) -> void in              if(success){                 let anchor = hk.getanchor()                  hk.getglucosesinceanchor(anchor, maxresults: 0)                     { (source, added, deleted, newanchor, error) -> void in                         var msg : string = string()                          if(deleted?.count > 0){                             msg += "deleted: \n" + (deleted?[0])!                             s in deleted!{                                 msg += s + "\n"                             }                         }                          if (added?.count > 0) {                             msg += "added: "                             s in added!{                                 msg += s + "\n"                             }                         }                          if(error != nil) {                             msg = "error = " + (error?.description)!                         }                          if(msg.isempty)                         {                             msg = "no changes"                         }                         debugprint(msg)                          if(newanchor != nil && newanchor != anchor){                             hk.saveanchor(newanchor!)                         }                          dispatch_async(dispatch_get_main_queue(), { () -> void in                             self.debuglabel.text = msg                         })                     }             }         }     }      override func didreceivememorywarning() {         super.didreceivememorywarning()         // dispose of resources can recreated.     } } 

note: know apple recommends set using hkobserverquery. did way in xamarin project , behavior same (no hkdeletedobjects getting sent). when trying out swift left out hkobserverquery simplicity.

remove predicate (predicate: nil) when instantiate query , you'll see more results, including deleted results. first time run (before hkqueryanchor has been saved) you'll results may want filter those; subsequent execution of query use saved anchor you'll see changes since saved anchor.

you want set updatehandler property on query before executing. set query run continuously in background calling update handler whenever there changes (adds or deletes). code near end of getglucosesinceanchor(...) looks like

... let anchoredquery = hkanchoredobjectquery(type: sampletype, predicate: nil, anchor: hkanchor, limit: int(maxresults), resultshandler: onanchorqueryresults) anchoredquery.updatehandler = onanchorqueryresults healthkitstore?.executequery(anchoredquery) ... 

Comments

Popular posts from this blog

html - Outlook 2010 Anchor (url/address/link) -

javascript - Why does running this loop 9 times take 100x longer than running it 8 times? -

Getting gateway time-out Rails app with Nginx + Puma running on Digital Ocean -