WatchKit本地化提示根本不显示,并且HealthKit授权提示带有很大的延迟Swift

问题描述 投票:2回答:1

我正在尝试通过使用GPS找出用户的位置并跟踪用户的心率。就位置功能(在单独的类中构建)而言,我正在使用CLLocationManager,在心率方面,我正在使用HealthKit框架。我已经在infop.list中设置了所有必要的属性。但是,我不明白为什么对于位置功能根本不显示授权提示,而就心率功能而言,该提示在很大的延迟后才出现。如果用户未授予授权权限,则无法查询任何值。在定位功能方面,我尝试在viewController中实现本地化功能,以及首先触发提示并将其重新用于手表。 (但是,这不应该是这样)到目前为止,我已经尝试了许多方法,但是无法解决。我希望你能帮助我。

我认为应该重点关注的类是LocationOutsideManager和HeartRateManager,它们都在InterfaceController中使用。

import WatchKit
import Foundation
import CoreLocation

protocol LocationOutsideDelegate {

    func processNewLocation(newLocation:CLLocation)
    func processLocationFailure(error:NSError)
}

class LocationOutsideManager: NSObject {

    let locationManager = CLLocationManager()
    var delegate: LocationOutsideDelegate
    let authorizationStatus = CLLocationManager.authorizationStatus()

    // setting up the delegate
    init(delegate:LocationOutsideDelegate){
        self.delegate = delegate
        super.init()

        // location service is "on" on users device
        if CLLocationManager.locationServicesEnabled() {
            locationManager.delegate = self
            // fast, but lower accuracy
            locationManager.desiredAccuracy =  kCLLocationAccuracyBest
            checkLocationAuthorization(status: authorizationStatus)
        }
    }

    func checkLocationAuthorization(status: CLAuthorizationStatus){

        switch status {
        case .notDetermined:
            locationManager.requestWhenInUseAuthorization()
        case .restricted, .denied:
            print("Location data is not available")
        case .authorizedAlways, .authorizedWhenInUse:
            locationManager.startUpdatingLocation()
        default:
            break
        }
    }
}

extension LocationOutsideManager: CLLocationManagerDelegate {

    // whenever authorization changes we want to check for state
    func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
        checkLocationAuthorization(status: status)
    }

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        // just interested in last and recent location in loc array
        guard let location = locations.last else{ return }
        // pass location data in delegate
        delegate.processNewLocation(newLocation: location)
    }

    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
        guard let locationError = error as? CLError else {
            print("other error: ", error.localizedDescription)
            return
        }

        switch locationError {
        case CLError.locationUnknown:
            delegate.processLocationFailure(error: locationError as NSError)
            print("location unknown")
        case CLError.denied:
            delegate.processLocationFailure(error: locationError as NSError)
            print("denied")
        default:
            delegate.processLocationFailure(error: locationError as NSError)
            print("other Core Location error")
        }

        delegate.processLocationFailure(error: locationError as NSError)
    }
}
import Foundation
import HealthKit

protocol HeartRateManagerDelegate {

    func handleNewHeartRate(newHeartRate:Double)
}

class HeartRateManager: NSObject{
    let heartRateManager = HKHealthStore()
    var delegate: HeartRateManagerDelegate
    var session: HKWorkoutSession?
    var currentQuery: HKQuery?

    init(delegate: HeartRateManagerDelegate){
        self.delegate = delegate
        super.init()
    }

    func startWorkout(){
        // If a workout has already been started, do nothing.
        if (session != nil) {
            return
        }
        // Configure the workout session.
        let workoutConfiguration = HKWorkoutConfiguration()
        workoutConfiguration.activityType = .running
        workoutConfiguration.locationType = .outdoor

        do {
            session = try HKWorkoutSession(configuration: workoutConfiguration)
            session?.delegate = self
        } catch {
            fatalError("Unable to create workout session")
        }

        heartRateManager.start(self.session!)

    }

    func stopWorkout(){
        if(session == nil){
            return
        }

        //heartRateManager.end(session!)
        session = nil
    }

    // query for heartrate values
    func heartRateQuery(_ startDate: Date) -> HKQuery? {
        let datePredicate = HKQuery.predicateForSamples(withStart: startDate, end: nil, options: .strictEndDate)

        let predicate = NSCompoundPredicate(andPredicateWithSubpredicates:[datePredicate])

        let heartRateQuery = HKAnchoredObjectQuery(type: HeartRate.hrType, predicate: predicate, anchor: nil, limit: Int(HKObjectQueryNoLimit)) { (query, sampleObjects, deletedObjects, newAnchor, error) -> Void in
            //Do nothing
        }

        heartRateQuery.updateHandler = {(query, samples, deleteObjects, newAnchor, error) -> Void in
            guard let samples = samples as? [HKQuantitySample] else {return}
            DispatchQueue.main.async {
                guard let sample = samples.first else { return }

                // after extraction of bpm value conversion to double
                let value = sample.quantity.doubleValue(for: HKUnit(from: "count/min"))
                print("Here is hv\(value)")
                self.delegate.handleNewHeartRate(newHeartRate: value)
            }

        }

        return heartRateQuery
    }



}

extension HeartRateManager: HKWorkoutSessionDelegate{

    func workoutSession(_ workoutSession: HKWorkoutSession, didChangeTo toState: HKWorkoutSessionState, from fromState: HKWorkoutSessionState, date: Date) {
        switch toState {
        case .running:
            //print(date)
            if let query = heartRateQuery(date){
                self.currentQuery = query
                heartRateManager.execute(query)
            }
        //Execute Query
        case .ended:
            //Stop Query
            heartRateManager.stop(self.currentQuery!)
            session = nil
        default:
            print("Unexpected state: \(toState)")
        }
    }

    func workoutSession(_ workoutSession: HKWorkoutSession, didFailWithError error: Error) {
        fatalError(error.localizedDescription)
    }

    func workoutSession(_ workoutSession: HKWorkoutSession, didGenerate event: HKWorkoutEvent) {
        print("\(event) generated!")
    }
}
import WatchKit
import Foundation
import HealthKit
import AVFoundation
import CoreMotion


// generate a short unique id
struct ShortCodeGenerator {

    private static let base62chars = [Character]("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")
    private static let maxBase : UInt32 = 62

    static func getCode(withBase base: UInt32 = maxBase, length: Int) -> String {
        var code = ""
        for _ in 0..<length {
            let random = Int(arc4random_uniform(min(base, maxBase)))
            code.append(base62chars[random])
        }
        return code
    }
}

// Date will be constructed in database --> server side
class InterfaceController: WKInterfaceController {

    var saveUrl: URL?

    // instance of locationOutside exist already at runtime
    var locationManager: LocationOutsideManager!
    let healthService: HealthDataService = HealthDataService()
    var heartRateManager: HeartRateManager!

    // Outlets for testing
    @IBOutlet weak var button: WKInterfaceButton!
    @IBOutlet weak var furtherSigLabels: WKInterfaceLabel!
    var settings = [String : Any]()

    // distinguish start recording heartbeat
    var isRecording = false

    //For workout session
    var currentQuery: HKQuery?
    var filename: String?
    var motionManager: MovementManager!
    var movement: String = ""


    var manualLat: Double = 0.0
    var manualLong: Double = 0.0

    override func awake(withContext context: Any?) {
        super.awake(withContext: context)

        healthService.authorizeHealthKitAccess { (success, error) in
            if success {
                print("HealthKit authorization received.")
            } else {
                print("HealthKit authorization denied!")
                if error != nil {
                    print("\(String(describing: error))")
                }
            }
        }
        heartRateManager = HeartRateManager(delegate: self)

        // initialize locationManager
        locationManager = LocationOutsideManager(delegate: self)
        motionManager = MovementManager(delegate: self)
    }

    override func willActivate() {
        // This method is called when watch view controller is about to be visible to user
        super.willActivate()
        motionManager.startUpdatingMotions()
    }

    override func didDeactivate() {
        // This method is called when watch view controller is no longer visible
        super.didDeactivate()
        motionManager.stopUpdatingMotions()
    }

    func sendToServer(params : Dictionary<String, String>){
        guard let url = URL(string:"http://13.125.244.168:80") else
        { print("URL could not be created")
            return
        }
        let requestBody = try? JSONSerialization.data(withJSONObject: params,  options: [])

        var urlRequest = URLRequest(url: url)
        //urlRequest.timeoutInterval = 240
        urlRequest.httpMethod = "POST"
        urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
        urlRequest.setValue("application/json", forHTTPHeaderField: "Accept")
        urlRequest.httpBody = requestBody

        let session = URLSession.shared

        let task = session.dataTask(with: urlRequest) { (data, response, error) in
            if let error = error {
                print("error:", error)
                return
            }

            do {
                guard let data = data else { return }
                guard let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: AnyObject] else { return }
                print("json:", json)
            } catch {
                print("error:", error)
            }
        }
        task.resume()
    }

    @IBAction func manualBtnPressed() {
        // manual reporting functionality
        // generating 6 character long unique id

        let uniqueId = ShortCodeGenerator.getCode(length: 6)
        let txtMsg = "I am student \(uniqueId). I need help!"
        print(txtMsg)

        if manualLat != 0.0 && manualLong != 0.0 {
            var latStr = String(format:"%.2f",manualLat)
            var longStr = String(format:"%.2f",manualLong)
            let request = NSMutableURLRequest(url: NSURL(string: "http://147.46.242.219/addmanual.php")! as URL)
            request.httpMethod = "POST"
            let postString = "a=\(manualLat)&b=\(manualLong)&c=\(txtMsg)"
            print(postString)
            request.httpBody = postString.data(using: .utf8)

            let task = URLSession.shared.dataTask(with: request as URLRequest) {
                data, response, error in

                if error != nil {
                    //print("error=\(error)")
                    return
                }

                //print("response = \(response)")

                let responseString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
                //print("responseString = \(responseString)")
            }

            task.resume()
        }
    }

    // when button clicked label is shown
    @IBAction func btnPressed() {

        if(!isRecording){
            let stopTitle = NSMutableAttributedString(string: "Stop Recording")
            stopTitle.setAttributes([NSAttributedString.Key.foregroundColor: UIColor.red], range: NSMakeRange(0, stopTitle.length))
            button.setAttributedTitle(stopTitle)
            isRecording = true
            heartRateManager.startWorkout() //Start workout session/healthkit streaming
        } else {
            let exitTitle = NSMutableAttributedString(string: "Start Recording")
            exitTitle.setAttributes([NSAttributedString.Key.foregroundColor: UIColor.red], range: NSMakeRange(0, exitTitle.length))
            button.setAttributedTitle(exitTitle)
            isRecording = false
            heartRateManager.stopWorkout()
            //healthStore.end(session!)

        }

    }

}


extension InterfaceController: LocationOutsideDelegate {

    func processNewLocation(newLocation: CLLocation) {
        let latitude = newLocation.coordinate.latitude
        let longitude = newLocation.coordinate.longitude
        print("Latitude \(latitude)")
        print("Longitude \(longitude)")

        let stringFrLat = "\(latitude)"
        let stringFrLong = "\(longitude)"
        var locationData = ["latitude": stringFrLat, "longitude":stringFrLong] as Dictionary<String,String>
        sendToServer(params: locationData)
    }

    func processLocationFailure(error: NSError) {
        print(error)
    }
}


extension InterfaceController: HeartRateManagerDelegate {

    func handleNewHeartRate(newHeartRate: Double) {
        print("New Heartrate \(newHeartRate)")
    }
}


extension InterfaceController: MovementDelegate {

    func evalMovForSending(toSend: Bool, gravStr: String, accelStr: String, rotationStr: String, attStr: String){

        let tmp = "\(gravStr), \(accelStr), \(rotationStr), \(attStr), "
        if toSend{
            print("Student has fallen down!")
            movement = "\(tmp) _1"
            print(movement)
        }else{
            movement = "\(tmp) _2"
            print(movement)
        }
    }

}

这里是xcode项目:https://filebin.net/0ybr2co7qutulfxx。我希望你能帮助我。非常感谢你。

ios swift watchkit
1个回答
0
投票

我也遇到同样的问题,您找到任何解决办法了吗?

© www.soinside.com 2019 - 2024. All rights reserved.