首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Swift HealthKit HKStatisticsCollectionQuery statisticsUpdateHandler并不总是被调用

Swift HealthKit HKStatisticsCollectionQuery statisticsUpdateHandler并不总是被调用
EN

Stack Overflow用户
提问于 2020-11-24 15:50:13
回答 1查看 920关注 0票数 2

我有一个测试项目,在这个测试项目中,我得到了一个用户在一周内每天下降的总次数。initialResultsHandler每一次都能完美地工作,但是statisticsUpdateHandler并不总是启动。如果您启动应用程序,然后转到健康应用程序并手动插入falls,切换回测试应用程序,您将看到今天更新的总数。在现实中,这是工作的前3-6次。从那以后,statisticsUpdateHandler就不再被打电话了。

奇怪的是,如果您删除数据,然后返回到测试应用程序,或者从比现在更早的时间添加数据,那么statisticsUpdateHandler就会被调用。这使我认为这与statisticsUpdateHandler结束日期有关。

苹果文档是相当清楚的,但是我担心他们可能遗漏了一些东西。

如果此属性设置为零,统计信息收集查询将在计算完初始结果后立即自动停止。如果此属性不是零,则查询的行为与观察者查询类似。它继续运行,监视HealthKit存储。如果将任何新的、匹配的示例保存到存储区,或者从存储中删除任何现有的匹配示例,则查询将在后台队列上执行更新处理程序。

是否有任何理由不调用statisticsUpdateHandler?我在下面包括了一个测试项目。

代码语言:javascript
复制
struct Falls: Identifiable{
    let id = UUID()
    let date: Date
    let value: Int
    
    var formattedDate: String{
        let formatter = DateFormatter()
        formatter.setLocalizedDateFormatFromTemplate("MM/dd/yyyy")
        return formatter.string(from: date)
    }
}
代码语言:javascript
复制
struct ContentView: View {
    @StateObject var manager = HealthKitManager()
    
    var body: some View {
        NavigationView{
            List{
                Text("Updates: \(manager.updates)")
                ForEach(manager.falls){ falls in
                    HStack{
                        Text(falls.value.description)
                        Text(falls.formattedDate)
                    }
                }
            }
            .overlay(
                ProgressView()
                    .scaleEffect(1.5)
                    .opacity(manager.isLoading ? 1 : 0)
            )
            .navigationTitle("Falls")
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
代码语言:javascript
复制
class HealthKitManager: ObservableObject{
    let healthStore = HKHealthStore()
    let fallType   = HKQuantityType.quantityType(forIdentifier: .numberOfTimesFallen)!
    @Published var isLoading = false
    @Published var falls = [Falls]()
    @Published var updates = 0

    init() {
        let healthKitTypesToRead: Set<HKSampleType> = [fallType]

        healthStore.requestAuthorization(toShare: nil, read: healthKitTypesToRead) { (success, error) in
            if let error = error{
                print("Error: \(error)")
            } else if success{
                self.startQuery()
            }
        }
    }
    
    func startQuery(){
        let now = Date()
        let cal = Calendar.current
        let sevenDaysAgo = cal.date(byAdding: .day, value: -7, to: now)!
        let startDate = cal.startOfDay(for: sevenDaysAgo)
        let predicate = HKQuery.predicateForSamples(withStart: startDate, end: now, options: [.strictStartDate, .strictEndDate])
        
        var interval = DateComponents()
        interval.day = 1
        
        // start from midnight
        let anchorDate = cal.startOfDay(for: now)
       
        let query = HKStatisticsCollectionQuery(
            quantityType: fallType,
            quantitySamplePredicate: predicate,
            options: .cumulativeSum,
            anchorDate: anchorDate,
            intervalComponents: interval
        )
        
        query.initialResultsHandler = { query, collection, error in
            guard let collection = collection else {
                print("No collection")
                DispatchQueue.main.async{
                    self.isLoading = false
                }
                return
            }
            
            collection.enumerateStatistics(from: startDate, to: Date()){ (result, stop) in
                guard let sumQuantity = result.sumQuantity() else {
                    return
                }
                
                let totalFallsForADay = Int(sumQuantity.doubleValue(for: .count()))
                let falls = Falls(date: result.startDate, value: totalFallsForADay)
                print(falls.value, falls.formattedDate)
                
                DispatchQueue.main.async{
                    self.falls.insert(falls, at: 0)
                }
            }
            
            print("initialResultsHandler done")
            DispatchQueue.main.async{
                self.isLoading = false
            }
        }
        
        
        query.statisticsUpdateHandler = { query, statistics, collection, error in
            print("In statisticsUpdateHandler...")
            guard let collection = collection else {
                print("No collection")
                DispatchQueue.main.async{
                    self.isLoading = false
                }
                return
            }
            
            DispatchQueue.main.async{
                self.isLoading = true
                self.updates += 1
                self.falls.removeAll(keepingCapacity: true)
            }
            
            collection.enumerateStatistics(from: startDate, to: Date()){ (result, stop) in
                guard let sumQuantity = result.sumQuantity() else {
                    return
                }
                
                let totalFallsForADay = Int(sumQuantity.doubleValue(for: .count()))
                let falls = Falls(date: result.startDate, value: totalFallsForADay)
                print(falls.value, falls.formattedDate)
                print("\n\n")

                DispatchQueue.main.async{
                    self.falls.insert(falls, at: 0)
                }
            }
            
            print("statisticsUpdateHandler done")
            DispatchQueue.main.async{
                self.isLoading = false
            }
        }
        
        
        isLoading = true
        healthStore.execute(query)
    }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-11-24 16:23:59

我非常专注于statisticsUpdateHandler以及开始和结束时间,所以我没有注意查询本身。事实证明,谓词就是问题所在。通过给它一个结束日期,它永远不会在初始谓词结束日期之外寻找样本。

将谓词改为该谓词解决了这个问题:

代码语言:javascript
复制
let predicate = HKQuery.predicateForSamples(withStart: startDate, end: nil, options: [.strictStartDate])
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64989989

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档