title: No haptic feedback
body: <p>My watchos app relies on haptic feedback working in the background. I have searched and searched over the internet on how to do this and have only learnt how to add things to my info.plist</p>
  
  <p>I do not want to use notifications to alert my user as its to cumbersome in terms of UI because this would be done too often.</p>
  
  <p>I read about workout sessions but can't get this to work.</p>
  
  <p>How do I allow haptic feedback to work while the wrist is lowered? The simplest way will be enough and I am not the most advanced with swift so please try explain fully!</p>
  
  <p>An example of my code is below. Please show me where to put it if I want background haptic feedback to work:</p>
  
  <p>My timer:</p>
  
  <pre><code> _ = Timer.scheduledTimer(timeInterval: 88, target: self, selector: "action", userInfo: nil, repeats: true)
  </code></pre>
  
  <p>My action:</p>
  
  <pre><code> func action() {
      print("action")
      WKInterfaceDevice.current().play(.success)
       imageObject.setImageNamed("number2")     
  }
  </code></pre>
  
  <p>This is what I'm doing with HKWorkout session but have absolute no idea whats going on.</p>
  
  <pre><code>  func workoutSession(_ workoutSession: HKWorkoutSession, didChangeTo toState: HKWorkoutSessionState, from fromState: HKWorkoutSessionState, date: Date) {
      switch toState {
      case .running:
          workoutDidStart(date)
      case .ended:
          workoutDidEnd(date)
      default:
          print("Unexpected state \(toState)")
      }
  }
  
  func workoutSession(_ workoutSession: HKWorkoutSession, didFailWithError error: Error) {
      // Do nothing for now
      print("Workout error")
  }
  
  
  func workoutDidStart(_ date : Date) {
      if let query = createHeartRateStreamingQuery(date) {
          self.currenQuery = query
          healthStore.execute(query)
      } else {
          label.setText("cannot start")
      }
  }
  
  func workoutDidEnd(_ date : Date) {
      healthStore.stop(self.currenQuery!)
      label.setText("---")
      session = nil
  }
  
  // MARK: - Actions
  @IBAction func startBtnTapped() {
      if (self.workoutActive) {
          //finish the current workout
          self.workoutActive = false
          self.startStopButton.setTitle("Start")
          if let workout = self.session {
              healthStore.end(workout)
          }
      } else {
          //start a new workout
          self.workoutActive = true
          self.startStopButton.setTitle("Stop")
          _ = Timer.scheduledTimer(timeInterval: 5, target: self, selector: "firsts", userInfo: nil, repeats: false)
  
  
          startWorkout()
      }
  
  }
  
  func startWorkout() {
  
      // If we have already started the workout, then do nothing.
      if (session != nil) {
          return
      }
  
      // Configure the workout session.
      let workoutConfiguration = HKWorkoutConfiguration()
      workoutConfiguration.activityType = .crossTraining
      workoutConfiguration.locationType = .indoor
  
      do {
          session = try HKWorkoutSession(configuration: workoutConfiguration)
          session?.delegate = self
      } catch {
          fatalError("Unable to create the workout session!")
      }
  
      healthStore.start(self.session!)
  }
  
  func createHeartRateStreamingQuery(_ workoutStartDate: Date) -&gt; HKQuery? {
  
  
      guard let quantityType = HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.heartRate) else { return nil }
      let datePredicate = HKQuery.predicateForSamples(withStart: workoutStartDate, end: nil, options: .strictEndDate )
      //let devicePredicate = HKQuery.predicateForObjects(from: [HKDevice.local()])
      let predicate = NSCompoundPredicate(andPredicateWithSubpredicates:[datePredicate])
  
  
      let heartRateQuery = HKAnchoredObjectQuery(type: quantityType, predicate: predicate, anchor: nil, limit: Int(HKObjectQueryNoLimit)) { (query, sampleObjects, deletedObjects, newAnchor, error) -&gt; Void in
          //guard let newAnchor = newAnchor else {return}
          //self.anchor = newAnchor
          self.updateHeartRate(sampleObjects)
      }
  
      heartRateQuery.updateHandler = {(query, samples, deleteObjects, newAnchor, error) -&gt; Void in
          //self.anchor = newAnchor!
          self.updateHeartRate(samples)
      }
      return heartRateQuery
  }
  
  func updateHeartRate(_ samples: [HKSample]?) {
      guard let heartRateSamples = samples as? [HKQuantitySample] else {return}
  
      DispatchQueue.main.async {
          guard let sample = heartRateSamples.first else{return}
          let value = sample.quantity.doubleValue(for: self.heartRateUnit)
          self.label.setText(String(UInt16(value)))
  
          // retrieve source from sample
          let name = sample.sourceRevision.source.name
          self.updateDeviceName(name)
          self.animateHeart()
      }
  }
  
  func updateDeviceName(_ deviceName: String) {
      deviceLabel.setText(deviceName)
  }
  
  func animateHeart() {
      self.animate(withDuration: 0.5) {
          self.heart.setWidth(60)
          self.heart.setHeight(90)
      }
  
      let when = DispatchTime.now() + Double(Int64(0.5 * double_t(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)
  
      DispatchQueue.global(qos: .default).async {
          DispatchQueue.main.asyncAfter(deadline: when) {
              self.animate(withDuration: 0.5, animations: {
                  self.heart.setWidth(50)
                  self.heart.setHeight(80)
              })            }
  
  
      }
  }
  </code></pre>
  
  <p>Look I don't even need heart rate data or anything at all but the taptic engine buzzing in the background. </p>