Dimitri T Dimitri T - 4 months ago 26
Swift Question

swift error "cannot assign value of type 'interface controller' to type HKWorkoutSessionDelegate'

I have an error message arising for watchOS code to measure heart rate in HealthKit, that is working fine in a different Xcode project. I've compared the code and they seem the same. the file is InterfaceController.swift.

For the line 'self.workoutsession?.delegate = self' I get the red flag error "cannot assign value of type 'interface controller' to type HKWorkoutSessionDelegate" Any ideas?

Here is the code for the function. The last para is the function with the error (The prior code is for context). Would appreciate your help!

import WatchKit
import Foundation
import HealthKit


class InterfaceController: WKInterfaceController {

@IBOutlet var label: WKInterfaceLabel!

@IBOutlet private weak var heart: WKInterfaceImage!

@IBOutlet var deviceLabel: WKInterfaceLabel!

@IBOutlet var startStopButton: WKInterfaceButton!

let healthStore = HKHealthStore()

//State of the app - is the workout activated
var workoutActive = false

// define the activity type and location
var workoutSession : HKWorkoutSession?
let heartRateUnit = HKUnit(fromString: "count/min")
var anchor = HKQueryAnchor(fromValue: Int(HKAnchoredObjectQueryNoAnchor))


override func awakeWithContext(context: AnyObject?) {
super.awakeWithContext(context)
}

override func willActivate() {
super.willActivate()

guard HKHealthStore.isHealthDataAvailable() == true else {
label.setText("not available")
return
}

guard let quantityType = HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierHeartRate) else {
displayNotAllowed()
return
}

let dataTypes = Set(arrayLiteral: quantityType)
healthStore.requestAuthorizationToShareTypes(nil, readTypes: dataTypes) { (success, error) -> Void in
if success == false {
self.displayNotAllowed()
}
}
}

func displayNotAllowed() {
label.setText("not allowed")
}

func workoutSession(workoutSession: HKWorkoutSession, didChangeToState toState: HKWorkoutSessionState, fromState: HKWorkoutSessionState, date: NSDate) {
switch toState {
case .Running:
workoutDidStart(date)
case .Ended:
workoutDidEnd(date)
default:
print("Unexpected state \(toState)")
}
}

func workoutSession(workoutSession: HKWorkoutSession, didFailWithError error: NSError) {
// Do nothing for now
NSLog("Workout error: \(error.userInfo)")
}

func workoutDidStart(date : NSDate) {
if let query = createHeartRateStreamingQuery(date) {
healthStore.executeQuery(query)
} else {
label.setText("cannot start")
}
}

func workoutDidEnd(date : NSDate) {
if let query = createHeartRateStreamingQuery(date) {
healthStore.stopQuery(query)
label.setText("---")
} else {
label.setText("cannot stop")
}
}

// MARK: - Actions
@IBAction func startBtnTapped() {
if (self.workoutActive) {
//finish the current workout
self.workoutActive = false
self.startStopButton.setTitle("Start")
if let workout = self.workoutSession {
healthStore.endWorkoutSession(workout)
}
} else {
//start a new workout
self.workoutActive = true
self.startStopButton.setTitle("Stop")
startWorkout()
}

}

func startWorkout() {
self.workoutSession = HKWorkoutSession(activityType: HKWorkoutActivityType.CrossTraining, locationType: HKWorkoutSessionLocationType.Indoor)

self.workoutSession?.delegate = self

healthStore.startWorkoutSession(self.workoutSession!)
}

Answer

self doesn't implement HKWorkoutSessionDelegate? You don't show that part of the code.

While you implemented the required methods, you have to change

class InterfaceController: WKInterfaceController {

to be

class InterfaceController: WKInterfaceController, HKWorkoutSessionDelegate {

which tells the compiler that the class implements that protocol.