【问题标题】:My Object that's Health Store are not refreshing data when it received a new data (in Health kit) in swift app我的 Health Store 对象在 swift 应用程序中收到新数据(在 Health kit 中)时没有刷新数据
【发布时间】:2021-03-06 11:45:06
【问题描述】:

我想开发从 Health kit(正念时间)加载数据的视图,因此我每 1 分钟使用 Timer 从 Apple watch 创建的 Health kit 中获取新数据,但 onReceive(Timer) 不会刷新新数据(它只传递以前的数据)

如果我打开另一个应用程序并回到这个应用程序,那么它会显示一个新数据

import SwiftUI

struct LoadingView: View {
    
     var healthStore : HealthStore? = HealthStore()
    @State private var timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
    @State var num : Int = 0
    @Binding var showModal: Bool
   
    var decription : String
    
   
    
    // MARK: - BODY
    var body: some View {
        
        VStack (alignment: .center){
            Spacer()
           WatchView()
            Spacer()
          
                Text(decription)
                   
                    .font(.callout)
                    .fontWeight(.semibold)
                    .padding(.horizontal,30)
                   
            Spacer()
            
            
        }
        .navigationBarBackButtonHidden(true)
        .onReceive(timer) { _ in
           
            
            if let healthStore = healthStore {
                healthStore.requestAuthorization { success in
                    if success {
                        healthStore.getDailyMindfulnessTime { time in
                            print("\(time)")
                            
                         
                            
                        }
                       
                           
                    } //: SUCCESS
                     
                }
            }
            
        }// ON RECEIVE
        .onDisappear(perform: {
            self.timer.upstream.connect().cancel()
        })//ON DISAPPEAR
        
    }
}

健康商店

import Foundation 
import HealthKit
class HealthStore {
    var healthStore : HKHealthStore?
    var query : HKStatisticsCollectionQuery?
    var querySampleQuery : HKSampleQuery?
    
    init(){
        // to check data is avaliable or not?
        if HKHealthStore.isHealthDataAvailable(){
            //Create instance of HKHealthStore
            healthStore = HKHealthStore()
        }
        
    }
    // Authorization
    func requestAuthorization(compleion: @escaping(Bool)-> Void){
        let stepType = HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.stepCount)!
        let mindfulSampleType = HKSampleType.categoryType(forIdentifier: .mindfulSession)!
        
        guard let healthStore = self.healthStore else { return compleion(false)}
        
        healthStore.requestAuthorization(toShare: [], read: [stepType,mindfulSampleType]) { (success, error) in
            compleion(success)
        }
    }
    //Calculate steps count
    func calculateSteps(completion : @escaping(HKStatisticsCollection?)->Void){
        let stepType = HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.stepCount)!
        
        let startDate  = Calendar.current.date(byAdding: .day,value: -7, to: Date())
        let anchorDate = Date.mondayAt12AM()
        let daily = DateComponents(day:1)
        
        let predicate = HKQuery.predicateForSamples(withStart: startDate, end: Date()
                                                    , options: .strictStartDate)
        //cumulativeSum  (Watch+Iphone)
       query =  HKStatisticsCollectionQuery(quantityType: stepType, quantitySamplePredicate: predicate, options: .cumulativeSum, anchorDate: anchorDate, intervalComponents: daily)
        
        query!.initialResultsHandler = { query, statisticsCollection , error in
            completion(statisticsCollection)
        }
        
        if let healthStore = self.healthStore, let query = self.query {
            healthStore.execute(query)
        }
    }
    
    // DailyMindfulnessTime
    func getDailyMindfulnessTime(completion: @escaping (TimeInterval) -> Void) {

                let sampleType = HKSampleType.categoryType(forIdentifier: .mindfulSession)!
                let sortDescriptor = NSSortDescriptor(key: HKSampleSortIdentifierEndDate, ascending: false)
                let startDate = Calendar.current.startOfDay(for: Date())
                let endDate = Calendar.current.date(byAdding: .day, value: 1, to: startDate)
                let predicate = HKQuery.predicateForSamples(withStart: startDate, end: endDate, options: .strictStartDate)

                 querySampleQuery = HKSampleQuery(sampleType: sampleType, predicate: predicate, limit: HKObjectQueryNoLimit, sortDescriptors: [sortDescriptor]) { (_, results, error) in
                    
                    if error != nil {
                        print(" HealthKit returned error while trying to query today's mindful sessions. The error was: \(String(describing: error?.localizedDescription))")
                    }
                    
                    if let results = results {
                        var totalTime = TimeInterval()
                        for result in results {
                            totalTime += result.endDate.timeIntervalSince(result.startDate)
                        }
                        completion(totalTime)
                    } else {
                        completion(0)
                    }
                }
        
        
            if let healthStore = self.healthStore, let querySampleQuery  = self.querySampleQuery {
            healthStore.execute(querySampleQuery)
                }

            }

    }

extension Date {
    static func mondayAt12AM() -> Date{
        return Calendar(identifier: .iso8601).date(from: Calendar(identifier: .iso8601).dateComponents([.yearForWeekOfYear,.weekOfYear],from: Date()))!
    }
    
}

【问题讨论】:

    标签: swiftui swift5


    【解决方案1】:

    首先,您在问题中写下您希望每分钟更新一次,但目前您每秒更新一次。 TimeInterval 是 Double 的类型别名,您在 Timer 中将其作为秒传递。所以在你的情况下应该是:

    @State private var timer = Timer.publish(every: 60, on: .main, in: .common).autoconnect()
    

    请注意,这意味着 onReceive 在 60 秒后调用,而不是立即调用。

    我测试了你的代码,对我来说效果很好。不幸的是,你没有包括你的手表视图,所以我不知道你在里面做什么。

    我假设 num 是你想要更新的变量,所以你需要调用:

    num += Int(time)
    

    在 getDailyMindfulnessTime 的闭包中。

    如果您想在 WatchView 中显示时间,请确保将 num 作为绑定传递。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多