Hello. I am building a BLE device that is Activity Fitness based and would like a "System Level" BLE connection on WatchOS using an ESP32 (I have built a test of this on the firmware side). Meaning I do not want my iOS app to pass the BLE connection to the WatchOS app. It seems like these App Level connections do not get as many background updates as a System Level connection, and also requires the WatchOS app to be launched to connect to the BLE device
The System Level BLE connection (WatchOS Settings > BLE > Health Devices) allows for auto connection in the background, and gets more reliable background communication between the BLE device and the Apple Watch
On the Apple MFi Page it only mentions iOS:
From Apple MFi Page:
:: Who does NOT need to join -
Developers and manufacturers of accessories that connect to an Apple device using only Bluetooth Low Energy, Core Bluetooth, or standard Bluetooth profiles supported by iOS
Does this apply to WatchOS as well?
So, if I am making an BLE device that is Activity Based, and has one of the allowable Health Device UUIDs, is the BLE System Connection allowed using any BLE chip? Including say an ESP32
I have built a test BLE firmware that is a Health Device UUID, and the WatchOS sees it as a health device
Is this fine then? No need for MFi application and also no need to worry about which BLE chip is used?
thanks
WatchKit
RSS for tagBuild apps that leverage watchOS features like background tasks, extended runtime sessions, and access to the Digital Crown using WatchKit.
Posts under WatchKit tag
68 Posts
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
I've been happily building and deploying my app to my iPhone and Watch S8, and the app was ready to submit to App Store Connect last night. However, when archiving it I got an error saying that my DynamicEventSelectionIntent was in multiple extensions. It was, kind of. When I started working on the complications I copied the Widgets intents into the complications, and left the name the same, but they were not in multiple targets.
It looks like the info plist only had one item in the IntentsSupported (because they're the same name), so I decided to rename them so I had a widget one and a complications one.
The problem I have now is that I can't deploy to my iPhone and Watch anymore because I'm getting this error:
This app contains a WatchKit app with one or more Siri Intents app extensions that declare IntentsSupported that are not declared in any of the companion app's Siri Intents app extensions. WatchKit Siri Intents extensions' IntentsSupported values must be a subset of the companion app's Siri Intents extensions' IntentsSupported values.
All I've done is rename one intent, and locate every instance of it in the info plist files, and add the appropriate new one into the right places.
Here's what I've got. Main App contains Widget and WidgetIntentHandler, plus Watch App, which contains Complications and ComplicationsIntentHandler.
Target: Main app: (I've removed everything that has no bearing on extensions.)
Target: Widget:
Target: WidgetIntentHandler:
Target: Watch App:
Target: Complications:
Target: ComplicationsIntentHandler:
Please, can someone tell me what should and should not be in the various parts, as I've tried for 12 hours now and I cannot get this to deploy to my iPhone anymore :( Thanks.
I have an objective-c watch app and have added a swift widget style compilation to it and am having problems. The complication works fine but the name in the iPhone watch app complication picker stubbornly remains as the watchkit app name despite me trying various ways of changing it.
Here are the various CF bundle name and display name values I am using:
phone app values
CFBundleIdentifier - com.Distribution-Systems-Associates.Tennis-Watch-v1
CFBundleName - $(PRODUCT_NAME)
CFBundleDisplayName - Tennis Scorekeeper
watchkit app
CFBundleIdentifier - com.Distribution-Systems-Associates.Tennis-Watch-v1.watchkitapp
CFBundleName - Tennis Scorekeeper
CFBundleDisplayName - Tennis Scorekeeper
WatchKit extension
CFBundleIdentifier - com.Distribution-Systems-Associates.Tennis-Watch-v1.watchkitapp.watchkitextension
CFBundleName - Tennis Scorekeeper
CFBundleDisplayName - Tennis Scorekeeper
__Watchkit complication __
CFBundleIdentifier - com.Distribution-Systems-Associates.Tennis-Watch-v1.watchkitapp.watchkitextension.Tennis-Watch-V1-Complication
Changing the values in the complication doesn't seem to matter. Every other name in both my iPhone and watch apps are as expected.
ChatGPT suggested that I try adding a localized name in the watchkit app but that didn't seem to do much of anything useful. I have run this though Chat quite a bit to see if I could get any accidental insights that way and while it has been interesting, it has also been not terribly helpful.
I didn't post any of the complication code because that seems to be fine. However, I can do that if needed. The complication works as intended (starts the app). The various names everywhere else show up as intended. It's just that this one name refuses to be overridden. Thoughts?
Topic:
App & System Services
SubTopic:
Widgets & Live Activities
Tags:
WatchKit
Swift
Objective-C
WidgetKit
How can I enable "Extended Runtime Sessions" for a companion watch app? Here https://developer.apple.com/documentation/watchkit/using-extended-runtime-sessions
in targets under 'Signing & Capabilities' I checked "Audio" and Session Type 'Mindfulness',
I created an ExtendedRuntimeManager.swift file. When running a simulation the error message says
"Extended Runtime Session ungültig: Reason=-1, Error=This application does not have appropriate permissions to schedule a session."
How does the app get the 'appropriate permissions'?
Topic:
Developer Tools & Services
SubTopic:
Swift Playground
Tags:
WatchKit
watchOS
Background Tasks
This is a bit of a headscratcher. Xcode 16 fyi.
I've written a standalone watchos app (with a stub ios app).
Distributes and works perfectly over Testflight.
I've submitted for app store and it passed the checks an I've released it for sale.
Told my brother to use a promo code to download it and show me how it looks and report me any nuisances.
He tells me there's no app neither on phone (expected) nor in watch. And he checked both the Watch ios app list and the watch.
I've gone through various GPTs and they've all told me the basic troubleshooting. That his watch might not be supported (wrong, it's a watch 10 ultra with latest updates and my min supported versions are hilariously low).
They've suggested that I might not have the right keys for making it standalone set, also no. They suggested that skip_install shouldn't be set to no; also wrong I think they're thinking xcode 13 and below. The stub ios app has a dependency on watchos app and also has an embed directive. I also checked the archive and saw the watchos app embedded indeed.
Again, the app works perfectly fine when distributed over testflight. And AFAIK that's a release build which I know for a fact because I had a problem with not giving healthkit entitlements to release (that was another but minor headscratcher at the time, when it was working over direct xcode upload).
Minor detail, I've written, test(flight)ed the app in UK and in English, my brother is in Turkey.
Of course now I immediately pulled the app out of sale because I don't want people paying and getting nothing, that's gonna cause a lot of trouble.
So I need any help I can get to
How to debug this without exposing the app and myself: is it possible to limit the release?
Obviously: what could be going wrong?
How the hell did I even pass app review? Is this maybe isolated to my brother's watch?
I'm more than happy to share project files and/or info.plist files(end products of them, because my plists are generated from project file).
I am working with a watchOS app in SwiftUI, and I am using the following code to dial a phone number from the watch:
var number = "123456789"
if let telURL = URL(string: "tel:\(number)") {
let wkExtension = WKExtension.shared()
wkExtension.openSystemURL(telURL)
}
The issue is that when I try to dial a number starting with a * (asterisk) or # (hash), it doesn't work. When dialing a regular number, it works fine.
Is there any way to get this to work?
I have an iOS app, and I am trying to add a companion WatchOS app. My iOS app depends on 2 libraries:
GoogleMobileAds
FirebaseAnalyticsWithoutAdIdSupport
When I add a new target for WatchOS, the preview build starts to fail. I am not adding any libraries to WatchOS. The Google Ads and Firebase Analytics libs are only under the iOS target.
I am unable to run the preview, I get an error when trying to build the watch scheme. The preview does not work. The build just crashes. I've included the error log below.
But, here are the steps I've tried so far:
Delete folders inside Derived Data
Run a clean build (Cmd + Option + Shift + K)
Delete scheme and create a new one
Reset Package Cache
Restart Xcode
Restart Macbook
But, it just does not work. I do not understand why the watchOS target is erroring for "GoogleUserMessagingPlatform" and "GoogleMobileAdsTarget" when those packages are not linked/used for the watchOS.
SchemeBuildError: Failed to build the scheme “timerWatch Watch App”
While building for watchOS Simulator, no library for this platform was found in '/Users/k/Library/Developer/Xcode/DerivedData/timer-dhkdhvfcqtfgskfdxpmupujswtuh/SourcePackages/artifacts/swift-package-manager-google-user-messaging-platform/UserMessagingPlatform/UserMessagingPlatform.xcframework'. (in target 'UserMessagingPlatformTarget' from project 'GoogleUserMessagingPlatform')
Build target UserMessagingPlatformTarget:
/Users/k/Library/Developer/Xcode/DerivedData/timer-dhkdhvfcqtfgskfdxpmupujswtuh/SourcePackages/artifacts/swift-package-manager-google-user-messaging-platform/UserMessagingPlatform/UserMessagingPlatform.xcframework:1:1: error: While building for watchOS Simulator, no library for this platform was found in '/Users/k/Library/Developer/Xcode/DerivedData/timer-dhkdhvfcqtfgskfdxpmupujswtuh/SourcePackages/artifacts/swift-package-manager-google-user-messaging-platform/UserMessagingPlatform/UserMessagingPlatform.xcframework'. (in target 'UserMessagingPlatformTarget' from project 'GoogleUserMessagingPlatform')
Build target GoogleMobileAdsTarget:
/Users/k/Library/Developer/Xcode/DerivedData/timer-dhkdhvfcqtfgskfdxpmupujswtuh/SourcePackages/artifacts/swift-package-manager-google-mobile-ads/GoogleMobileAds/GoogleMobileAds.xcframework:1:1: error: While building for watchOS Simulator, no library for this platform was found in '/Users/k/Library/Developer/Xcode/DerivedData/timer-dhkdhvfcqtfgskfdxpmupujswtuh/SourcePackages/artifacts/swift-package-manager-google-mobile-ads/GoogleMobileAds/GoogleMobileAds.xcframework'. (in target 'GoogleMobileAdsTarget' from project 'GoogleMobileAds')
Hi,
I am getting an error stating "Argument passed to call that takes no arguments". I want this Apple Watch App to measure and store RR Intervals from the PPG sensor on the Apple Watch for Heart Rate Variability calculations. Please help me fix this, I can't figure it out. Here is my code:
heartbeatQuery = HKHeartbeatSeriesQuery(predicate: predicate,
dataReceivedHandler: { (query, timeSinceLastBeat, ended, error) in
// Switch to main thread for UI updates
DispatchQueue.main.async {
if let error = error {
print("Heartbeat query error: (error.localizedDescription)")
self.fetchErrorMessage = "Heartbeat query error: (error.localizedDescription)"
// Consider stopping the workout session if the query fails critically
// self.stopWorkoutSession()
return
}
if ended {
print("Heartbeat query indicates series ended.")
}
// Append valid RR intervals
if timeSinceLastBeat > 0 {
self.rrIntervals.append(timeSinceLastBeat)
self.beatCount += 1
}
} // End DispatchQueue.main.async
}) // End query data handler
// --- END OF PROBLEMATIC INITIALIZER ---
// Execute the query if it was created successfully
It recommends the fix as removing this part:
'(predicate: predicate,
dataReceivedHandler: { (query, timeSinceLastBeat, ended, error) in
// Switch to main thread for UI updates
DispatchQueue.main.async {
if let error = error {
print("Heartbeat query error: (error.localizedDescription)")
self.fetchErrorMessage = "Heartbeat query error: (error.localizedDescription)"
// Consider stopping the workout session if the query fails critically
// self.stopWorkoutSession()
return
}
if ended {
print("Heartbeat query indicates series ended.")
}
// Append valid RR intervals
if timeSinceLastBeat > 0 {
self.rrIntervals.append(timeSinceLastBeat)
self.beatCount += 1
}
} // End DispatchQueue.main.async
})'
But after I remove that it says "Cannot assign value of type 'HKHeartbeatSeriesQuery.Type' to type 'HKHeartbeatSeriesQuery'" PLEASE HELP ME
Thanks
My research group is using watch sensors (accelerometers, gyroscopes) to track wrist motion to detect and measure eating. https://cecas.clemson.edu/ahoover/bite-counter/
We are running an HKWorkoutSession on the watch so that the app can run for an extended period of time (up to 12 hr) and continue to sense and process motion data.
Our app is adding to the activity rings, making it look like the user is exercising the entire time our app is running. Is there a method to prevent our app from contributing to the activity ring measures?
Topic:
App & System Services
SubTopic:
Health & Fitness
Tags:
WatchKit
Health and Fitness
SensorKit
WorkoutKit
Hi everyone!
I’m a new developer diving into my first Apple Watch project, and I’m really excited to get started! This app relies heavily on using the most precise location data possible.
Could anyone point me to some official documentation or helpful resources on how to achieve high-accuracy location tracking specifically for watchOS? Any tips or best practices would also be greatly appreciated!
Thanks in advance for your help!
We are developing a mobile app focused on lone worker protection, which does not include any fitness tracking features.
We require the use of HKWorkoutSession solely to enable background execution of critical safety-related code.
Could you please confirm whether this use of HKWorkoutSession is permitted under App Store Review guidelines, given that our app does not offer fitness or workout-related functionality?
I am trying to track a user's real-time sleep state using heart rate data, but I have encountered several issues:
When using HKSampleQuery on the phone to fetch heart rate data, I can only retrieve data recorded before the app comes to the foreground or before it is terminated and restarted (see related issue: https://developer.apple.com/forums/thread/774953).
I attempted to get data on the Apple Watch and send updates to the phone via Watch Connectivity. However, if I use WKExtendedRuntimeSession, although I can obtain data on the watch, once the watch screen goes off, it can no longer transmit data via Watch Connectivity to the phone (since I cannot guarantee the app will remain in the foreground when lying in bed).
On the other hand, using HKWorkoutSession results in interference with the activity rings and causes the heart rate sensor to run too frequently, which I worry may affect the battery life of the watch.
Is there an elegant solution for tracking a user's heart rate data for sleep monitoring?
** Facing issue for watch unreachable, I have tried for real device as well simulator**
if let controller = window?.rootViewController as? FlutterViewController {
let channel = FlutterMethodChannel(
name: "watchconnectivity",
binaryMessenger: controller.binaryMessenger)
channel.setMethodCallHandler({ [weak self] (call, result) in
switch call.method {
case "sendToWatch":
guard let watchSession = self?.session else {
print("❌ Watch session not initialized")
result(false)
return
}
guard watchSession.isPaired else {
print("❌ Watch not paired")
result(false)
return
}
guard watchSession.isReachable else {
print("❌")
print("isPaired: \(watchSession.isPaired)")
print("isWatchAppInstalled: \(watchSession.isWatchAppInstalled)")
print("isComplicationEnabled: \(watchSession.isComplicationEnabled)")
result(false)
return
}
guard let arguments = call.arguments as? [String: Any] else {
print("❌ Invalid arguments format")
result(false)
return
}
if watchSession.isWatchAppInstalled {
try? watchSession.updateApplicationContext(["forceLaunch": true])
}
print("📤 Sending message to Watch: \(arguments)")
watchSession.sendMessage(arguments,
replyHandler: { response in
print("✅ Message sent successfully")
result(true)
},
errorHandler: nil
)
default:
result(FlutterMethodNotImplemented)
}
})
}
Hello all,
I have run into a weird situation in my watchOS app with a companion iOS app.
Issue: Watch fails to receive sendMessage string sent from phone while watch is in foreground. This is not consistent and seems to happen randomly under certain conditions.
Order of operations: User Opens phone app & watch app -> user presses "sendMessage" button, func is called -> watch does not receive message while in foreground
Condition explanation: To my knowledge, without a HealthKit workout session active, the apple watch is not available to receive messages (using any internal library transmission type) from its iOS companion app while the watch screen is not in the foreground (i.e. inactive). However, my issue is that sometimes, while the watch IS in the foreground, it does not receive the companion app's message. Additionally, this is not resolved by force quitting both iOS and watchOS apps. The only way I have gotten this issue to go away is by restarting both the phone and the watch. Again, it is not a consistent behavior and seemingly happens randomly. This behavior has been observed across multiple different beta testers on different hardware.
This is only apparent when transmitting from Phone -> Watch. I have not experienced any transmission issues when transmitting Watch -> Phone.
My team and I have speculated that it could be an issue with WCSession.isReachable returning true before we transmit the message but changing to false before the hardware actually transmits. However, this wouldn't explain why the watch would not be available while in the foreground. This is just a preliminary thought.
My goal in posting on here is to see if anyone else has experienced this, or if it's a known bug.
All message protocols have been coded to follow Apple's WCSession documentation as closely as possible.
Hardware specs:
Watch Model: A2093 (series 5)
WatchOS ver: 10.6.1
Phone: MU693LL/A (15 pro max)
iOS ver: 18.3.2
XCode ver: 16.0
We have a watchOS app that provides many configurable widgets. Those widgets are configured and installed with help of AppIntent:
public struct RectComplAppIntent: AppIntent, WidgetConfigurationIntent, CustomIntentMigratedAppIntent {
@Parameter(title: "Style")
var style: String?
....
}
However when I print WidgetInfos with getCurrentConfigurations(), I sometimes got nil for configuration. At the same time widgets are not loaded. Exact steps:
User installs the pre-cofnigured .watchface.
Complications are not loaded since configuration is missing. I print getCurrentConfigurations() and get entries like this:
WidgetInfo:
- configuration: nil
- widgetConfigurationIntent: nil
- family: accessoryRectangular
- kind: Rectangle
Then user force-touches a face and opens editing mode. Returns to watch app, prints infos:
WidgetInfo:
- configuration: <INIntent: 0x780d290> {
style = vol1Logo;
}
- widgetConfigurationIntent: nil
- family: accessoryRectangular
- kind: Rectangle
– Suddenly intent appears with the correct style and complications start to show up.
How do you think, why it happens? Why after .watchface install all the WidgetInfo has nil intent (configuration)? What helps them to load later?
You can try this face yourself: https://cdn.watchfaces.co/watchfaces/glance-minimalist.watchface
Topic:
App & System Services
SubTopic:
Automation & Scripting
Tags:
WatchKit
watchOS
WidgetKit
App Intents
I have followed this video on implementing a custom view for the watchOS 11 Smart Stack Live Activities. However, the UI of my iOS app keeps showing up on the watchOS.
`struct widgetLiveActivity: Widget {
@Environment(.activityFamily) var activityFamily
var body: some WidgetConfiguration {
ActivityConfiguration(for: widgetAttributes.self) { context in
switch activityFamily {
case .small, _:
Text("WatchOS UI")
case .medium:
Text("iOS UI")
.activitySystemActionForegroundColor(Color.black)
} dynamicIsland: { context in ... }
.supplementalActivityFamilies([.small, .medium])
}
}`
I'm developing a single target watchOS app that obtains HealthKit information. I have the "Background Delivery" option checked under "Signing & Capabilities" for the watch target. The app does HKObserverQueries in the foreground that work as I would expect. But when I click the Digital Crown to return to clock face, the HKObserverQuery activity stops. I'm using Xcode 15.4, on Mac 14.5 and a Apple Watch Series 4 running 10.5.
I'm working on a watchOS app that has an iOS counterpart. There will be a subscription required to unlock functionality and I would like the user to be able to make the purchase on either the iPhone or the watch and have both apps unlock.
The first link below says that StoreKit 2's Transaction.currentEntitlements will not work in this case like it does with extensions. The second link says it might work but doesn't in the sandbox.
What is the best way to make this work? Will it just work in the App Store? Should I use WCSession to send the purchase information from one platform to the other and store it in the keychain? Something else?
Via https://www.revenuecat.com/blog/engineering/ios-in-app-subscription-tutorial-with-storekit-2-and-swift/
"Transaction.currentEntitlements can be used in extensions the same way it was used in the previous steps. This works for extensions like Widgets and Intents. However, an iOS app with a companion watchOS app will not work even though Transaction.currentEntitlements can be executed in it. A companion watch app does not stay updated with the same transaction history as its iOS app because they are separate platforms."
Via https://developer.apple.com/forums/thread/739963
"In TestFlight I was able to confirm that the Watch app and IOS app share in-app purchases. It seems the problems confirming this with Storekit and Sandbox are limits of the testing environments."
Hi,
I'll start by saying that I'm a new developer for apps for Apple devices, especially for Apple Watch, so please have mercy
I'm trying to create an app for Apple Watch (WatchOs 10+) and I have a problem, my interface is made up of 3 buttons, one at the bottom of the screen and two smaller ones positioned on the top of the screen, each in their respective corners (one at the top right and the other at the top left).
By positioning these buttons on the top of the screen, the top right button is covered by the default Apple time, and I would like to move it to the center, thus creating two side buttons and the time in the center.
I'm also asking if there's a way to remove it since it's not useful to me, but reading some forums it seems that without it I don't pass the app verification, so I'm waiting for your advice.
The only app I've seen in circulation on the app store that has the centered clock is petey.
I get a crash in Apple Watch simulator (Series 9 45mm 18.0) as soon as the app launch if I type anything on external keyboard (just hitting command key for instance to capture a screenshot). Same crash on series 7 (45mm, OS 18.1)
But app works normally when I use mouse to interact with the app on simulator.
App does not crash on real device (Watch 4 OS 10.4.1).
Nor does it crash on Series 6 simulator (44 mm OS 17.4).
Here are the log I could collect (apparently, they contain sensitive language !!! so I attach as a file.:
Attached logs