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