|
@@ -11,19 +11,19 @@ protocol GarminManager {
|
|
|
/// Prompts the user to select Garmin devices, returning the chosen devices in a publisher.
|
|
/// Prompts the user to select Garmin devices, returning the chosen devices in a publisher.
|
|
|
/// - Returns: A publisher that eventually outputs an array of selected `IQDevice` objects.
|
|
/// - Returns: A publisher that eventually outputs an array of selected `IQDevice` objects.
|
|
|
func selectDevices() -> AnyPublisher<[IQDevice], Never>
|
|
func selectDevices() -> AnyPublisher<[IQDevice], Never>
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
/// Updates the currently tracked device list. This typically persists the device list and
|
|
/// Updates the currently tracked device list. This typically persists the device list and
|
|
|
/// triggers re-registration for any relevant ConnectIQ events.
|
|
/// triggers re-registration for any relevant ConnectIQ events.
|
|
|
/// - Parameter devices: The new array of `IQDevice` objects to track.
|
|
/// - Parameter devices: The new array of `IQDevice` objects to track.
|
|
|
func updateDeviceList(_ devices: [IQDevice])
|
|
func updateDeviceList(_ devices: [IQDevice])
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
/// Takes raw JSON-encoded watch-state data and dispatches it to any connected watch apps.
|
|
/// Takes raw JSON-encoded watch-state data and dispatches it to any connected watch apps.
|
|
|
/// - Parameter data: The JSON-encoded data representing the watch state.
|
|
/// - Parameter data: The JSON-encoded data representing the watch state.
|
|
|
func sendWatchStateData(_ data: Data)
|
|
func sendWatchStateData(_ data: Data)
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
/// The devices currently known to the app. May be loaded from disk or user selection.
|
|
/// The devices currently known to the app. May be loaded from disk or user selection.
|
|
|
var devices: [IQDevice] { get }
|
|
var devices: [IQDevice] { get }
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
/// An async closure that, when called, returns the latest watch state data (encoded as `Data`)
|
|
/// An async closure that, when called, returns the latest watch state data (encoded as `Data`)
|
|
|
/// to be sent to the watch on demand (e.g., when the watch pings "status").
|
|
/// to be sent to the watch on demand (e.g., when the watch pings "status").
|
|
|
var watchStateDataProvider: (() async -> Data)? { get set }
|
|
var watchStateDataProvider: (() async -> Data)? { get set }
|
|
@@ -34,46 +34,45 @@ protocol GarminManager {
|
|
|
/// Concrete implementation of `GarminManager` that handles device registration, data persistence,
|
|
/// Concrete implementation of `GarminManager` that handles device registration, data persistence,
|
|
|
/// and sending watch-state updates via the Garmin ConnectIQ SDK.
|
|
/// and sending watch-state updates via the Garmin ConnectIQ SDK.
|
|
|
final class BaseGarminManager: NSObject, GarminManager, Injectable {
|
|
final class BaseGarminManager: NSObject, GarminManager, Injectable {
|
|
|
-
|
|
|
|
|
// MARK: - Config
|
|
// MARK: - Config
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
private enum Config {
|
|
private enum Config {
|
|
|
/// Example watchface UUID
|
|
/// Example watchface UUID
|
|
|
static let watchfaceUUID = UUID(uuidString: "EC3420F6-027D-49B3-B45F-D81D6D3ED90A")
|
|
static let watchfaceUUID = UUID(uuidString: "EC3420F6-027D-49B3-B45F-D81D6D3ED90A")
|
|
|
/// Example data field UUID
|
|
/// Example data field UUID
|
|
|
static let watchdataUUID = UUID(uuidString: "71CF0982-CA41-42A5-8441-EA81D36056C3")
|
|
static let watchdataUUID = UUID(uuidString: "71CF0982-CA41-42A5-8441-EA81D36056C3")
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// MARK: - Dependencies & Properties
|
|
// MARK: - Dependencies & Properties
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
/// NotificationCenter used for responding to `.openFromGarminConnect` notifications.
|
|
/// NotificationCenter used for responding to `.openFromGarminConnect` notifications.
|
|
|
@Injected() private var notificationCenter: NotificationCenter!
|
|
@Injected() private var notificationCenter: NotificationCenter!
|
|
|
@Injected() private var watchManager: WatchManager!
|
|
@Injected() private var watchManager: WatchManager!
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
/// Persists the user’s device list between app launches.
|
|
/// Persists the user’s device list between app launches.
|
|
|
@Persisted(key: "BaseGarminManager.persistedDevices") private var persistedDevices: [GarminDevice] = []
|
|
@Persisted(key: "BaseGarminManager.persistedDevices") private var persistedDevices: [GarminDevice] = []
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
/// Router for presenting alerts or navigation flows (injected via Swinject).
|
|
/// Router for presenting alerts or navigation flows (injected via Swinject).
|
|
|
private let router: Router
|
|
private let router: Router
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
/// Garmin ConnectIQ shared instance for all watch interactions.
|
|
/// Garmin ConnectIQ shared instance for all watch interactions.
|
|
|
private let connectIQ = ConnectIQ.sharedInstance()
|
|
private let connectIQ = ConnectIQ.sharedInstance()
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
/// Keeps references to watch apps (both watchface & data field) for each registered device.
|
|
/// Keeps references to watch apps (both watchface & data field) for each registered device.
|
|
|
private var watchApps: [IQApp] = []
|
|
private var watchApps: [IQApp] = []
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
/// A subject that dispatches watch-state dictionaries to the watch on a throttled schedule.
|
|
/// A subject that dispatches watch-state dictionaries to the watch on a throttled schedule.
|
|
|
private let watchStateSubject = PassthroughSubject<NSDictionary, Never>()
|
|
private let watchStateSubject = PassthroughSubject<NSDictionary, Never>()
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
/// A set of Combine cancellables for managing the lifecycle of various subscriptions.
|
|
/// A set of Combine cancellables for managing the lifecycle of various subscriptions.
|
|
|
private var cancellables = Set<AnyCancellable>()
|
|
private var cancellables = Set<AnyCancellable>()
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
/// Holds a promise used when the user is selecting devices (via `showDeviceSelection()`).
|
|
/// Holds a promise used when the user is selecting devices (via `showDeviceSelection()`).
|
|
|
private var deviceSelectionPromise: Future<[IQDevice], Never>.Promise?
|
|
private var deviceSelectionPromise: Future<[IQDevice], Never>.Promise?
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
/// Async closure returning JSON-encoded watch state. Called when the watch pings "status".
|
|
/// Async closure returning JSON-encoded watch state. Called when the watch pings "status".
|
|
|
var watchStateDataProvider: (() async -> Data)?
|
|
var watchStateDataProvider: (() async -> Data)?
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
/// Array of Garmin `IQDevice` objects currently being tracked.
|
|
/// Array of Garmin `IQDevice` objects currently being tracked.
|
|
|
/// Changing this property triggers re-registration and updates persisted devices.
|
|
/// Changing this property triggers re-registration and updates persisted devices.
|
|
|
private(set) var devices: [IQDevice] = [] {
|
|
private(set) var devices: [IQDevice] = [] {
|
|
@@ -84,42 +83,42 @@ final class BaseGarminManager: NSObject, GarminManager, Injectable {
|
|
|
registerDevices(devices)
|
|
registerDevices(devices)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// MARK: - Initialization
|
|
// MARK: - Initialization
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
/// Creates a new `BaseGarminManager`, injecting required services and restoring any persisted devices.
|
|
/// Creates a new `BaseGarminManager`, injecting required services and restoring any persisted devices.
|
|
|
/// - Parameter resolver: Swinject resolver for injecting dependencies like the Router.
|
|
/// - Parameter resolver: Swinject resolver for injecting dependencies like the Router.
|
|
|
init(resolver: Resolver) {
|
|
init(resolver: Resolver) {
|
|
|
- self.router = resolver.resolve(Router.self)!
|
|
|
|
|
|
|
+ router = resolver.resolve(Router.self)!
|
|
|
super.init()
|
|
super.init()
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// Initialize ConnectIQ with a custom URL scheme and override delegate
|
|
// Initialize ConnectIQ with a custom URL scheme and override delegate
|
|
|
connectIQ?.initialize(withUrlScheme: "Trio", uiOverrideDelegate: self)
|
|
connectIQ?.initialize(withUrlScheme: "Trio", uiOverrideDelegate: self)
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// Inject any property wrappers that need the resolver
|
|
// Inject any property wrappers that need the resolver
|
|
|
injectServices(resolver)
|
|
injectServices(resolver)
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// Restore previously persisted devices
|
|
// Restore previously persisted devices
|
|
|
restoreDevices()
|
|
restoreDevices()
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// Subscribe to relevant notifications and watch-state changes
|
|
// Subscribe to relevant notifications and watch-state changes
|
|
|
subscribeToOpenFromGarminConnect()
|
|
subscribeToOpenFromGarminConnect()
|
|
|
subscribeToWatchState()
|
|
subscribeToWatchState()
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// MARK: - Device & App Registration
|
|
// MARK: - Device & App Registration
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
/// Registers the given devices for ConnectIQ events (device status changes) and watch app messages.
|
|
/// Registers the given devices for ConnectIQ events (device status changes) and watch app messages.
|
|
|
/// It also creates and registers watch apps (watchface + data field) for each device.
|
|
/// It also creates and registers watch apps (watchface + data field) for each device.
|
|
|
/// - Parameter devices: The devices to register.
|
|
/// - Parameter devices: The devices to register.
|
|
|
private func registerDevices(_ devices: [IQDevice]) {
|
|
private func registerDevices(_ devices: [IQDevice]) {
|
|
|
// Clear out old references
|
|
// Clear out old references
|
|
|
watchApps.removeAll()
|
|
watchApps.removeAll()
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
for device in devices {
|
|
for device in devices {
|
|
|
// Listen for device-level status changes
|
|
// Listen for device-level status changes
|
|
|
connectIQ?.register(forDeviceEvents: device, delegate: self)
|
|
connectIQ?.register(forDeviceEvents: device, delegate: self)
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// Create a watchface app
|
|
// Create a watchface app
|
|
|
guard
|
|
guard
|
|
|
let watchfaceUUID = Config.watchfaceUUID,
|
|
let watchfaceUUID = Config.watchfaceUUID,
|
|
@@ -128,7 +127,7 @@ final class BaseGarminManager: NSObject, GarminManager, Injectable {
|
|
|
debug(.watchManager, "Garmin: Could not create watchface app for device \(String(describing: device.uuid))")
|
|
debug(.watchManager, "Garmin: Could not create watchface app for device \(String(describing: device.uuid))")
|
|
|
continue
|
|
continue
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// Create a watch data field app
|
|
// Create a watch data field app
|
|
|
guard
|
|
guard
|
|
|
let watchdataUUID = Config.watchdataUUID,
|
|
let watchdataUUID = Config.watchdataUUID,
|
|
@@ -137,24 +136,24 @@ final class BaseGarminManager: NSObject, GarminManager, Injectable {
|
|
|
debug(.watchManager, "Garmin: Could not create data-field app for device \(String(describing: device.uuid))")
|
|
debug(.watchManager, "Garmin: Could not create data-field app for device \(String(describing: device.uuid))")
|
|
|
continue
|
|
continue
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// Track both apps for potential messages
|
|
// Track both apps for potential messages
|
|
|
watchApps.append(watchfaceApp)
|
|
watchApps.append(watchfaceApp)
|
|
|
watchApps.append(watchDataFieldApp)
|
|
watchApps.append(watchDataFieldApp)
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// Register to receive app-messages from the watchface (if you also want data-field messages,
|
|
// Register to receive app-messages from the watchface (if you also want data-field messages,
|
|
|
// register that, too)
|
|
// register that, too)
|
|
|
connectIQ?.register(forAppMessages: watchfaceApp, delegate: self)
|
|
connectIQ?.register(forAppMessages: watchfaceApp, delegate: self)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
/// Restores previously persisted devices from local storage into `devices`.
|
|
/// Restores previously persisted devices from local storage into `devices`.
|
|
|
private func restoreDevices() {
|
|
private func restoreDevices() {
|
|
|
devices = persistedDevices.map(\.iqDevice)
|
|
devices = persistedDevices.map(\.iqDevice)
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// MARK: - Combine Subscriptions
|
|
// MARK: - Combine Subscriptions
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
/// Subscribes to the `.openFromGarminConnect` notification, parsing devices from the given URL
|
|
/// Subscribes to the `.openFromGarminConnect` notification, parsing devices from the given URL
|
|
|
/// and updating the device list accordingly.
|
|
/// and updating the device list accordingly.
|
|
|
private func subscribeToOpenFromGarminConnect() {
|
|
private func subscribeToOpenFromGarminConnect() {
|
|
@@ -165,12 +164,12 @@ final class BaseGarminManager: NSObject, GarminManager, Injectable {
|
|
|
let self = self,
|
|
let self = self,
|
|
|
let url = notification.object as? URL
|
|
let url = notification.object as? URL
|
|
|
else { return }
|
|
else { return }
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
self.parseDevices(for: url)
|
|
self.parseDevices(for: url)
|
|
|
}
|
|
}
|
|
|
.store(in: &cancellables)
|
|
.store(in: &cancellables)
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
/// Subscribes to any watch-state dictionaries published via `watchStateSubject`, and throttles them
|
|
/// Subscribes to any watch-state dictionaries published via `watchStateSubject`, and throttles them
|
|
|
/// so updates aren’t sent too frequently. Each update triggers a broadcast to all watch apps.
|
|
/// so updates aren’t sent too frequently. Each update triggers a broadcast to all watch apps.
|
|
|
private func subscribeToWatchState() {
|
|
private func subscribeToWatchState() {
|
|
@@ -181,20 +180,20 @@ final class BaseGarminManager: NSObject, GarminManager, Injectable {
|
|
|
}
|
|
}
|
|
|
.store(in: &cancellables)
|
|
.store(in: &cancellables)
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// MARK: - Parsing & Broadcasting
|
|
// MARK: - Parsing & Broadcasting
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
/// Parses devices from a Garmin Connect URL and updates our `devices` property.
|
|
/// Parses devices from a Garmin Connect URL and updates our `devices` property.
|
|
|
/// - Parameter url: The URL provided by Garmin Connect containing device selection info.
|
|
/// - Parameter url: The URL provided by Garmin Connect containing device selection info.
|
|
|
private func parseDevices(for url: URL) {
|
|
private func parseDevices(for url: URL) {
|
|
|
let parsed = connectIQ?.parseDeviceSelectionResponse(from: url) as? [IQDevice]
|
|
let parsed = connectIQ?.parseDeviceSelectionResponse(from: url) as? [IQDevice]
|
|
|
devices = parsed ?? []
|
|
devices = parsed ?? []
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// Fulfill any pending promise in case this is in response to `selectDevices()`.
|
|
// Fulfill any pending promise in case this is in response to `selectDevices()`.
|
|
|
deviceSelectionPromise?(.success(devices))
|
|
deviceSelectionPromise?(.success(devices))
|
|
|
deviceSelectionPromise = nil
|
|
deviceSelectionPromise = nil
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
/// Sends the given state dictionary to all known watch apps (watchface & data field) by checking
|
|
/// Sends the given state dictionary to all known watch apps (watchface & data field) by checking
|
|
|
/// if each app is installed and then sending messages asynchronously.
|
|
/// if each app is installed and then sending messages asynchronously.
|
|
|
/// - Parameter state: The dictionary representing the watch state to be broadcast.
|
|
/// - Parameter state: The dictionary representing the watch state to be broadcast.
|
|
@@ -210,9 +209,9 @@ final class BaseGarminManager: NSObject, GarminManager, Injectable {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// MARK: - GarminManager Conformance
|
|
// MARK: - GarminManager Conformance
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
/// Prompts the user to select one or more Garmin devices, returning a publisher that emits
|
|
/// Prompts the user to select one or more Garmin devices, returning a publisher that emits
|
|
|
/// the final array of selected devices once the user finishes selection.
|
|
/// the final array of selected devices once the user finishes selection.
|
|
|
/// - Returns: An `AnyPublisher` emitting `[IQDevice]` on success, or empty array on error/timeout.
|
|
/// - Returns: An `AnyPublisher` emitting `[IQDevice]` on success, or empty array on error/timeout.
|
|
@@ -225,7 +224,7 @@ final class BaseGarminManager: NSObject, GarminManager, Injectable {
|
|
|
}
|
|
}
|
|
|
// Store the promise so we can fulfill it when the user selects devices
|
|
// Store the promise so we can fulfill it when the user selects devices
|
|
|
self.deviceSelectionPromise = promise
|
|
self.deviceSelectionPromise = promise
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// Show Garmin's default device selection UI
|
|
// Show Garmin's default device selection UI
|
|
|
self.connectIQ?.showDeviceSelection()
|
|
self.connectIQ?.showDeviceSelection()
|
|
|
}
|
|
}
|
|
@@ -233,13 +232,13 @@ final class BaseGarminManager: NSObject, GarminManager, Injectable {
|
|
|
.replaceEmpty(with: [])
|
|
.replaceEmpty(with: [])
|
|
|
.eraseToAnyPublisher()
|
|
.eraseToAnyPublisher()
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
/// Updates the manager’s list of devices, typically after user selection or manual changes.
|
|
/// Updates the manager’s list of devices, typically after user selection or manual changes.
|
|
|
/// - Parameter devices: The new array of `IQDevice` objects to track.
|
|
/// - Parameter devices: The new array of `IQDevice` objects to track.
|
|
|
func updateDeviceList(_ devices: [IQDevice]) {
|
|
func updateDeviceList(_ devices: [IQDevice]) {
|
|
|
self.devices = devices
|
|
self.devices = devices
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
/// Converts the given JSON data into an NSDictionary and sends it to all known watch apps.
|
|
/// Converts the given JSON data into an NSDictionary and sends it to all known watch apps.
|
|
|
/// - Parameter data: JSON-encoded data representing the latest watch state. If decoding fails,
|
|
/// - Parameter data: JSON-encoded data representing the latest watch state. If decoding fails,
|
|
|
/// the method logs an error and does nothing else.
|
|
/// the method logs an error and does nothing else.
|
|
@@ -253,9 +252,9 @@ final class BaseGarminManager: NSObject, GarminManager, Injectable {
|
|
|
}
|
|
}
|
|
|
watchStateSubject.send(dict)
|
|
watchStateSubject.send(dict)
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// MARK: - Helper: Sending Messages
|
|
// MARK: - Helper: Sending Messages
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
/// Sends a message to a given IQApp with optional progress and completion callbacks.
|
|
/// Sends a message to a given IQApp with optional progress and completion callbacks.
|
|
|
/// - Parameters:
|
|
/// - Parameters:
|
|
|
/// - msg: The dictionary to send to the watch app.
|
|
/// - msg: The dictionary to send to the watch app.
|
|
@@ -282,9 +281,8 @@ final class BaseGarminManager: NSObject, GarminManager, Injectable {
|
|
|
// MARK: - Extensions
|
|
// MARK: - Extensions
|
|
|
|
|
|
|
|
extension BaseGarminManager: IQUIOverrideDelegate, IQDeviceEventDelegate, IQAppMessageDelegate {
|
|
extension BaseGarminManager: IQUIOverrideDelegate, IQDeviceEventDelegate, IQAppMessageDelegate {
|
|
|
-
|
|
|
|
|
// MARK: - IQUIOverrideDelegate
|
|
// MARK: - IQUIOverrideDelegate
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
/// Called if the Garmin Connect Mobile app is not installed or otherwise not available.
|
|
/// Called if the Garmin Connect Mobile app is not installed or otherwise not available.
|
|
|
/// Typically, you would show an alert or prompt the user to install the app from the store.
|
|
/// Typically, you would show an alert or prompt the user to install the app from the store.
|
|
|
func needsToInstallConnectMobile() {
|
|
func needsToInstallConnectMobile() {
|
|
@@ -297,9 +295,9 @@ extension BaseGarminManager: IQUIOverrideDelegate, IQDeviceEventDelegate, IQAppM
|
|
|
)
|
|
)
|
|
|
router.alertMessage.send(messageCont)
|
|
router.alertMessage.send(messageCont)
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// MARK: - IQDeviceEventDelegate
|
|
// MARK: - IQDeviceEventDelegate
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
/// Called whenever the status of a registered Garmin device changes (e.g., connected, not found, etc.).
|
|
/// Called whenever the status of a registered Garmin device changes (e.g., connected, not found, etc.).
|
|
|
/// - Parameters:
|
|
/// - Parameters:
|
|
|
/// - device: The device whose status has changed.
|
|
/// - device: The device whose status has changed.
|
|
@@ -320,7 +318,7 @@ extension BaseGarminManager: IQUIOverrideDelegate, IQDeviceEventDelegate, IQAppM
|
|
|
debug(.watchManager, "Garmin: unknown state (\(String(describing: device.uuid)))")
|
|
debug(.watchManager, "Garmin: unknown state (\(String(describing: device.uuid)))")
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// MARK: - IQAppMessageDelegate
|
|
// MARK: - IQAppMessageDelegate
|
|
|
|
|
|
|
|
/// Called when a message arrives from a Garmin watch app (watchface or data field).
|
|
/// Called when a message arrives from a Garmin watch app (watchface or data field).
|
|
@@ -337,12 +335,12 @@ extension BaseGarminManager: IQUIOverrideDelegate, IQDeviceEventDelegate, IQAppM
|
|
|
else {
|
|
else {
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
do {
|
|
do {
|
|
|
// Fetch the latest watch state (async) and encode it to JSON data
|
|
// Fetch the latest watch state (async) and encode it to JSON data
|
|
|
let watchState = await watchManager.setupWatchState()
|
|
let watchState = await watchManager.setupWatchState()
|
|
|
let watchStateData = try JSONEncoder().encode(watchState)
|
|
let watchStateData = try JSONEncoder().encode(watchState)
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// Now send that JSON to the watch
|
|
// Now send that JSON to the watch
|
|
|
sendWatchStateData(watchStateData)
|
|
sendWatchStateData(watchStateData)
|
|
|
} catch {
|
|
} catch {
|
|
@@ -350,5 +348,4 @@ extension BaseGarminManager: IQUIOverrideDelegate, IQDeviceEventDelegate, IQAppM
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
}
|
|
}
|