簡體   English   中英

HealthKit 錯誤:嘗試刪除 HKQuantitySample 時“找不到要刪除的對象”

[英]HealthKit Error: “Failed to find some objects for deletion” when attempting to delete HKQuantitySample

我有一個鍛煉 Apple Watch 應用程序,它啟動HKWorkout並使用原始 Healthkit API(不是較新的鍛煉生成器)將HKQuantitySamples (DistanceWalkingRunning 樣本)保存到 Apple Health 中。 然后,我想讓用戶能夠在配套的 iPhone 應用程序上刪除這些內容(例如,他們忘記在手表上結束鍛煉)。 無論我在下面使用的 3 種刪除樣本的方法中的哪一種,我總是會收到此錯誤。 我知道一個應用程序只能刪除由同一應用程序保存的樣本,但樣本的HKSource是阻止我在 iPhone 上刪除的手表應用程序這一事實嗎? 我不認為這是故意的。 還有其他原因我無法刪除這些樣本嗎?

private func deleteRunningAndWalkingSamplesFrom(startDate: Date, endDate: Date) {
        
        let healthStore = HKHealthStore()
        
        guard let distanceWalkingAndRunningType:HKQuantityType = HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.distanceWalkingRunning) else {
            return
        }
        
        let predicate = HKQuery.predicateForSamples(withStart: startDate, end: endDate)
        
        let distanceWalkingAndRunningQuery = HKSampleQuery(sampleType: distanceWalkingAndRunningType,
                                                           predicate: predicate,
                                                           limit: (HKObjectQueryNoLimit),
                                                           sortDescriptors: nil)
        { (query:HKSampleQuery, results:[HKSample]?, error:Error?) -> Void in
            
            if let unwrappedError = error {
                print("Error trying to delete distance samples = \(unwrappedError)")
                return 
            }
            
            guard let unwrappedResults = results as? [HKQuantitySample] else {
                print("Couldn't cast results as [HKQuantitySample] in deleteRunninAndWalkingSamples")
                return
            }
       
//(1) Look through samples and try to delete   
//            for sample in unwrappedResults {
//                healthStore.delete(sample) { success, error in
//                    if let error = error {
//                        print("error attempting to delete runningAndWalkinGSample with startDate of \(sample.startDate) error = \(error)")
//                    }
//
//                    if success {
//                        print("successfully delete sample with startDate of \(sample.startDate)")
//                    }
//                }
//            }
 
//(2) Delete objects with predicate                
//            healthStore.deleteObjects(of: distanceWalkingAndRunningType, predicate: predicate) { success, deleteCount, error in
//                if let error = error {
//                    print("error attempting to delete runningAndWalkinGSamplesFrom shift = \(error)")
//                }
//
//                if success {
//                    print("successfully deleted \(deleteCount) samples")
//                }
//            }
            
        
       //(3) Delete all samples        
       healthStore.delete(unwrappedResults) { success, error in
                if let error = error {
                    print("error attempting to delete runningAndWalkinGSamplesFrom shift = \(error)")
                }

                if success {
                    print("success deleting runningAndWalkingSamples ")
                    
                }

            }
            
        }
        healthStore.execute(distanceWalkingAndRunningQuery)
            
            
        
        
    }

我創建了一個示例應用程序,但無法重現該問題:

import SwiftUI
import HealthKit

final class HealthManager: ObservableObject {
    let quantityType = HKQuantityType.quantityType(forIdentifier: .distanceWalkingRunning)!
    let healthStore = HKHealthStore()
    
    func requestAuthorization() {
        healthStore.requestAuthorization(toShare: [quantityType], read: [quantityType]) { [weak self] success, error in
            print(success, error?.localizedDescription ?? "")

            self?.createMockData { [weak self] success, error in
                print(success, error?.localizedDescription ?? "")

                self?.deleteMockData { success, error in
                    print(success, error?.localizedDescription ?? "")
                }
            }
        }
    }
    
    func createMockData(completion: @escaping (Bool, Error?) -> ()) {
        let sample = HKQuantitySample(type: quantityType,
                                      quantity: .init(unit: .inch(), doubleValue: 1000),
                                      start: Date().addingTimeInterval(-1000),
                                      end: Date().addingTimeInterval(-10))
        healthStore.save(sample, withCompletion: completion)
    }
    
    func deleteMockData(completion: @escaping (Bool, Error?) -> ()) {
        let predicate = HKQuery.predicateForSamples(withStart: .distantPast, end: .distantFuture)
        let distanceWalkingAndRunningQuery = HKSampleQuery(sampleType: quantityType,
                                                           predicate: predicate,
                                                           limit: HKObjectQueryNoLimit,
                                                           sortDescriptors: nil) { [weak self] (query, results, error) in

            if let unwrappedError = error {
                completion(false, unwrappedError)
                return
            }
            
            guard let unwrappedResults = results as? [HKQuantitySample] else {
                completion(false, NSError(domain: "dom", code: 1, userInfo: [
                    NSLocalizedDescriptionKey: "Couldn't cast results as [HKQuantitySample] in deleteRunninAndWalkingSamples"
                ]))
                
                return
            }
            
            guard !unwrappedResults.isEmpty else {
                completion(false, NSError(domain: "dom", code: 2, userInfo: [
                    NSLocalizedDescriptionKey: "Nothing to delete"
                ]))
                
                return
            }

            self?.healthStore.delete(unwrappedResults, withCompletion: completion)
        }
        
        healthStore.execute(distanceWalkingAndRunningQuery)
    }
}


@main
struct TestApp: App {
    @StateObject var healthManager = HealthManager()
    
    @SceneBuilder var body: some Scene {
        WindowGroup {
            NavigationView {
                ContentView()
                    .onAppear {
                        healthManager.requestAuthorization()
                    }
            }        
        }
        
        WKNotificationScene(controller: NotificationController.self, category: "myCategory")
    }
}

請確保您已執行以下所有步驟:

  1. 在您的應用中添加Health entitlement
  2. Info.plist添加Usage description文本
  3. 請求授權
  4. 授予授權
  5. 保存一些有效的樣本數據
  6. 查詢數據
  7. 檢查結果是否不為空且有效
  8. 刪除結果數據

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM