Ios WatchKit本地化提示根本不显示,HealthKit授权提示延迟时间很长

Ios WatchKit本地化提示根本不显示,HealthKit授权提示延迟时间很长,ios,swift,watchkit,Ios,Swift,Watchkit,我试图通过使用GPS和跟踪用户的心率来找出用户的位置。 在位置功能方面(在单独的类中构建),我使用CLLocationManager,在心率方面,我使用HealthKit框架。 我已在infop.list中设置了所有必要的属性。但是,我不明白为什么对于位置功能和心率功能,授权提示根本没有出现,提示出现在非常大的延迟之后。如果用户未授予授权权限,则无法查询任何值。在位置功能方面,我尝试在viewController中实现本地化功能,以及最初触发提示符并将其重新用于手表。(但是,不应该是这样) 到目

我试图通过使用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)
    }
}
导入WatchKit
进口基金会
进口健康套件
进口AVF基金会
导入CoreMotion
//生成一个简短的唯一id
结构短代码生成器{
私有静态let base62chars=[Character](“0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvxyz”)
专用静态let maxBase:UInt32=62
静态func getCode(withBase-base:UInt32=maxBase,长度:Int)->String{
var code=“”
对于0中的u0..服务器端
类InterfaceController:WKInterfaceController{
var saveUrl:URL?
//locationOutside的实例已在运行时存在
var locationManager:LocationOutsideManager!
让healthService:HealthDataService=HealthDataService()
var heartRateManager:heartRateManager!
//测试插座
@IBOUTLE弱var按钮:WKInterfaceButton!
@IBOutlet弱标签:WKInterfaceLabel!
变量设置=[String:Any]()
//开始记录心跳
var isRecording=false
//参加训练课程
var currentQuery:HKQuery?
变量文件名:字符串?
var motionManager:MovementManager!
变量移动:String=“”
var手动车床:双=0.0
var manualLong:双精度=0.0
覆盖函数唤醒(withContext:有吗?){
super.awake(withContext:context)
healthService.authorizeHealthKitAccess{(成功,错误)位于
如果成功{
打印(“收到HealthKit授权”)
}否则{
打印(“HealthKit授权被拒绝!”)
如果错误!=nil{
打印(“\(字符串(描述:错误))”)
}
}
}
heartRateManager=heartRateManager(代表:自我)
//初始化locationManager
locationManager=LocationOutsideManager(代表:自我)
motionManager=MovementManager(代理:self)
}
重写func willActivate(){
//当监视视图控制器即将对用户可见时,调用此方法
super.willActivate()
motionManager.startUpdatingMotions()
}
重写func diddactivate(){
//当监视视图控制器不再可见时,调用此方法
超级
motionManager.StopUpdateingMotions()的
}
func sendToServer(参数:字典){
guard let url=url(字符串:http://13.125.244.168:80)其他
{打印(“无法创建URL”)
返回
}
让requestBody=try?JSONSerialization.data(使用jsonObject:params,选项:[])
var urlRequest=urlRequest(url:url)
//urlRequest.timeoutInterval=240
urlRequest.httpMethod=“POST”
urlRequest.setValue(“应用程序/json”,用于HttpHeaderField:“内容类型”)
setValue(“application/json”,用于httpheaderfield:“Accept”)
urlRequest.httpBody=requestBody
让session=URLSession.shared
让task=session.dataTask(带:urlRequest){(数据、响应、错误)在
如果let error=error{
打印(“错误:”,错误)
返回
}
做{
guard let data=data else{return}
guard let json=try JSONSerialization.jsonObject(with:data,options:[])作为?[String:AnyObject]else{return}
打印(“json:”,json)
}抓住{
打印(“错误:”,错误)
}
}
task.resume()
}
@iAction func manualBtnPressed()操作功能{
//手动报告功能
//生成6个字符长的唯一id
让uniqueId=ShortCodeGenerator.getCode(长度:6)
让txtMsg=“我是学生\(唯一标识)。我需要帮助!”
打印(txtMsg)
如果manualLat!=0.0和manualLong!=0.0{
var LATSR=字符串(格式:“%.2f”,手动LAT)
var longStr=字符串(格式:“%.2f”,manualLong)
let request=NSMutableURLRequest(url:NSURL(字符串:)http://147.46.242.219/addmanual.php“”!作为URL)
request.httpMethod=“POST”
让postString=“a=\(manualLat)&b=\(manualLong)&c=\(txtMsg)”
打印(postString)
request.httpBody=postString.data(使用:.utf8)
让task=URLSession.shared.dataTask(其中:request作为URLRequest){
数据、响应、错误
如果错误!=nil{
//打印(“错误=\(错误)”)
返回
}
//打印(“响应=\(响应)”)
让responseString=NSString(数据:data!,编码:String.encoding.utf8.rawValue)
//打印(“responseString=\(responseString)”)
}
task.resume()
}
}
//单击按钮时,将显示标签
@IBActi
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)
        }
    }

}