Sivu 1/1

HealthKit, observerit ja anchoredqueryt

Lähetetty: 23.6.2016 klo 14.38
Kirjoittaja Fakap
Yritän integroida Applen HealthKitiä iOS-sovellukseemme niin, että milloin tahansa HealthKitiin syötetään tiettyä dataa, sovelluksemme havaitsee sen ja hakee uuden datan käsittelyyn. Ohjelmointikielenä Swift ja targettina iOS 8.0+.

Enabloin jokaiselle seuraamallemme sampletyypille background deliveryn ja luon niille HKObserverQueryt, joiden updatehandlerilla kutsun funktiota, jolla haen datan HealthKitistä. En kuitenkaan ymmärrä, miksi kaikki observerit reagoivat, kun Health-sovelluksessa lisään yhden sampletyypin dataa. Luulin, että observerit seuraavat vain tiettyä datatyyppiä.

Koodi: Valitse kaikki

for sampleTypeToRead in self.dataTypesToRead as! Set<HKSampleType> {
    self.healthKitStore.enableBackgroundDeliveryForType(sampleTypeToRead, frequency: .Immediate) {
        (success, error) in
        
        // Define update handler for background deliveries
        let updateHandler: (HKObserverQuery, HKObserverQueryCompletionHandler, NSError?) -> Void = {
            [unowned self] query, completionHandler, error in
            
            self.synchronizeRecentData(sampleTypeToRead)
            
            completionHandler()
        }
        
        let observerQuery = HKObserverQuery(sampleType: sampleTypeToRead, predicate: nil, updateHandler: updateHandler)
        self.healthKitStore.executeQuery(observerQuery)
    }
    
}
Toinen ongelma on, että uuden datan hakemiseen tarkoitetttu HKAnchoredQuery ei palaa luotettavasti, jos se ajetaan taustalla observerqueryn avulla. Josku query palaa heti, joskus viiveellä ja joskus vasta kun tuon sovelluksen takaisin eteen. Mistä tämä johtuu?

Koodi: Valitse kaikki

func synchronizeRecentData(sampleType: HKSampleType) {
    
    let completionHandler: (HKAnchoredObjectQuery, [HKSample]?, Int, NSError?) -> Void = {
        [unowned self] query, results, newAnchor, error in
        
        // Update queryAnchor
        self.queryAnchors[sampleType] = newAnchor
        
        // Handle results here
    }
    
    let query = HKAnchoredObjectQuery(type: sampleType,
                                      predicate: nil,
                                      anchor: self.queryAnchors[sampleType]!,
                                      limit: HKObjectQueryNoLimit,
                                      completionHandler: completionHandler)
    self.healthKitStore.executeQuery(query)
}
Bonuskysymyksenä haluaisin tietää milloin käyttää strong ja milloin weak referenssiä. Lueskelen aiheesta parhaillaan, mutta koodini suhteen saa heittää jo nyt suosituksia.

Re: HealthKit, observerit ja anchoredqueryt

Lähetetty: 17.7.2016 klo 16.12
Kirjoittaja spiidi78
HealthKit-ongelmiin en osaa vastata, koska en ole koskaan siihen koskenut, mutta jos tuo bonuskysymys on vielä auki, niin hyvänä nyrkkisääntönä voisi pitää, että käytä aina strong referencejä, PAITSI jos jaat olion referencen sen lapsiolioille ja tallennat sen sinne, käytä weak referenceä (weak reference ei kasvata reference countia). Näin ollen emo-olio kuolee kun se nillataan, eikä jää vuotamaan muistia siksi, että lapsiolioilla on referencet emoon vielä olemassa (eli emo-olion ref.count > 0). Lapsioliothan kuolevat samalla, eikä invalidoitunutta weak referenssiä emoon voi enää käyttää muutenkaan.

Jos tuon ns. emo-olion referenssejä tallennetaan strongina muuallekin (joka ei siis omista emo-oliota), niin sitten pitää vaan muistaa päivittää referenssit jos vanha olio tapetaan ja tehdään uusi tilalle. Muuten se jää taas henkiin vuotamaan muistia, tai pahimmassa tapauksessa käytetään useaa eri arvoja sisältävää oliota huomaamatta eri puolilla softaa ja sit ihmetellään, miksi homma ei toimi oikein.