davidgyoung
davidgyoung

Reputation: 65015

Check if Apple Watch is not currently connected

I am trying to detect if a user's Apple watch is currently active using this code:

if WCSession.isSupported()  {
  let session = WCSession.default
  session.delegate = self
  session.activate() 
}

But even after I power off the watch, I get a callback to session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) with activationState == .activated.

Is this expected? Is there any way to actually check if the watch and the iPhone are connected?

EDIT: I also note that if I run the same code inside a simulator, I get the exact same callback with activationState == .activated, yet isPaired == false. It sounds to me like .activated basically is the default state. I'm not even sure how to get .deactivated

EDIT 2: I actually do not have a WatchKit extension and would rather not create one for simplicity. I am simply trying to detect if a paired watch is in range, powered on and communicating so I can tell if my apps local notifications might be delivered to the watch.

Upvotes: 1

Views: 1969

Answers (3)

Alan Corbett
Alan Corbett

Reputation: 1

Use the 'activationState' property:

@available(iOS 9.3, *)
public enum WCSessionActivationState : Int, @unchecked Sendable {

    case notActivated = 0

    case inactive = 1

    case activated = 2
}

Upvotes: 0

DoesData
DoesData

Reputation: 7057

EDIT

I understand what you're asking now. The issue is that if you check isPaired you get true, even if the app is launched and the watch is not connected.

Example:

import WatchConnectivity

func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

    if WCSession.isSupported() {
      let session = WCSession.default
      session.delegate = self
      session.activate()
    }

    return true
  }
}

extension AppDelegate: WCSessionDelegate {
  func session(
    _ session: WCSession,
    activationDidCompleteWith activationState: WCSessionActivationState,
    error: Error?) {

    switch session.activationState {

    case .notActivated:
      print("Session no activated")
    case .inactive:
      print("Session inactive")
    case .activated:
      print("Session activated")
    @unknown default:
      break
    }

    if let err = error {
      print("ERROR: \(err.localizedDescription)")
    }

    if session.isPaired {
      print("Current phone is paired to an apple watch!")
    }

    print("reachable: \(session.isReachable)")
  }

  func sessionDidBecomeInactive(_ session: WCSession) {
    print("Session just became inactive")
  }

  func sessionDidDeactivate(_ session: WCSession) {
    print("session did deactivate")
  }
}

This results in the following output with the watch powered on or off

Session activated
Current phone is paired to an apple watch!
reachable: false

Note isReachable is always false because you don't have a watch extension.

Looking at this question there is no solution to this problem. I don't think you can determine this information without a watch extension / app.

Also note that you cannot access the WKInterfaceDevice outside of the watch app.

Upvotes: 1

Grzegorz Krukowski
Grzegorz Krukowski

Reputation: 19872

You are looking for: isPaired property of WCSession.

After calling activateSession and getting callback you can check if Watch is paired there.

If you need to know if app is installed on Watch - check isWatchAppInstalled.

Upvotes: 1

Related Questions