I have a simple wrapper class around WCSession to allow for easier unit testing. I'm trying to update it to Swift 6 concurrency standards, but running into some issues. One of them is in the sendMessage function (docs here
It takes [String: Any] as a param, and returns them as the reply. Here's my code that calls this:
@discardableResult
public func sendMessage(_ message: [String: Any]) async throws -> [String: Any] {
return try await withCheckedThrowingContinuation { (continuation: CheckedContinuation<[String: Any], Error>) in
wcSession.sendMessage(message) { response in
continuation.resume(returning: response) // ERROR HERE
} errorHandler: { error in
continuation.resume(throwing: error)
}
}
}
However, I get this error:
Sending 'response' risks causing data races; this is an error in the Swift 6 language mode
Which I think is because Any is not Sendable. I tried casting [String: Any] to [String: any Sendable] but then it says:
Conditional cast from '[String : Any]' to '[String : any Sendable]' always succeeds
Any ideas on how to get this to work?
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
131 Posts
Sort by:
Post
Replies
Boosts
Views
Activity
I’ve developed an Apple Watch extension for an existing iOS app. When I run the app on the watch via Xcode using the simulator, everything works fine. However, when I try to install it on my iPhone, the Watch app doesn’t show it in the "Available Apps" list, so I can't install it on the watch.
The Apple Watch is connected to my iPhone, and I can see other apps available for installation without any issues.
I also created a brand new project with watchOS support to troubleshoot, but the same problem occurred.
Any ideas on how to resolve this?
I am writing an app that records accelerometer data in the background. When we call sensor.accelerometerData(from:to:), the for loop when iterating CMSensorDataList suspends/pauses as the watch screen turns off and resumes when app comes to foreground. Is there a way we can keep the processing on until it completes? I used Location Updates capability in Background Modes as a hack but it will make my app rejected from App store just to acquire capability for background execution.
Please note that our data is comprised of larger sets, say hours. We retrieve data in batches of 30 minutes each but this also does not complete.
This is a repost as it seems to be a reoccurring issue.
‘I have a number of accessories setup on homekit and everything works fine from my phone. However, recently, no homekit accessories works on apple watch, everything is no response (on watch face or through siri). Everything still works on the phone. iOS 16.5, Watch OS 9.5.1’
I have the same issue with iPhone 14 pro ios 18.1 apple watch 9 watch os 11.1
tried turning off and on restarting app renaming home this is beta software but was hoping there was an easy fix.
https://forums.developer.apple.com/forums/thread/685317
Having read the above discussion, I can add there’s one problematic exception on watchOS to the rule that .didBecomeActiveNotification is fired when the Control Center or any other overlay (such as a long-look notification) is dismissed. It’s when it’s dismissed not by the user, but just allowed to dsimiss itself after a period (as determined by Settings > Wake Duration).
This is a problem for any Watch workout app because when one of these overlays is covering the app, it’s considered by the system to be backgounded for purposes of applying the 15% avg CPU load over 60 seconds criteria for being terminated for using too much CPU in the background, so I have discovered.
In the case of these overlays covering an app, the app never gets a .didEnterBackgroundNotification call to know that it should attempt to reduce its activity, when the user presses the Side Button to show the Control Center, which is by design, as I understand it.
The app does get a .willResignActiveNotification when the Control Center covers it, but there is no corresponding .didBecomeActiveNotification when the system dismisses the Control Center after 2 minutes or so.
So if the app reduces its actvity in an attempt to reduce CPU load when covered by the Control Center overlay, it has no way to know it has become active again, in the special case of the Control Center timing out and being dismissed by the system.
What could be done to reduce the likelihood of the system terminating the app in this situation, and maintain the app's functionality and usability?
I’d like to migrate my watchOS app (bundled with an iOS app) from a dual-target to a single-target setup. I remember Xcode used to have a menu item (Editor -> Validate Settings) that would prompt you to initiate the migration process. However, I can’t seem to find a ‘Validate Settings’ option in the latest Xcode 16. Has "Validate Settings" been removed in xcode16 ?
Thanks!
My Watch app is a workout app that has to be careful to minimize CPU load when backgrounded to get below the 15% avg/60 s in order to avoid being terminated by the system.
Accordingly I have logic to detect a transition to the background using a .onChange(of: scenePhase) { phase in… } handler which works well for cases where the app is backgrounded - it is able to reduce its CPU load to just 6-9% while backgrounded.
But a special case of the change to scenePhase presents a challenge - when an overlay such as the Control Center or a long-look notification presents, there is no transition to .background, only to .inactive. This is a problem because the system nevertheless imposes the background CPU limit on the app while it’s being covered by the overlay, even though the app didn’t get the .background transition on the scenePhase handler.
To further complicate matters, it now seems with watchOS 11 that whenever a transition is made in the screen cadence from .live to .seconds, the scenePhase handler is called with a transition to .inactive. Which is a problem because this transition has to be distinguished from the case of the overlay presentation - the cadence change has no CPU usage implications as long as the app remains foregrounded, but the overlay presentation does, and the system will terminate the app if it exceeds 15% avg/60s.
My question: how can I distinguish between the two causes of the transition to .inactive for the two cases: 1) when the overlay presents, and 2) when the display shifts to the slow cadence?
I'm attempting to create a standalone watchOS app that fetches the prayer timings of my local mosque in JSON format via an API call. I want the app to fetch the prayer timings in the background, but only once per day, at the start of the day (when prayer timings change, i.e., midnight).
I'm trying to implement this using SwiftUI's backgroundTask modifier as explained in the docs and in this WWDC22 video.
I made sure to enable the Background Modes capability, and this is what my app's Info.plist looks like:
However, I've been unable to get it to work. I would appreciate any assistance I can get and feedback for improvements I can make, even with the Info.plist if anything is incorrect about it. Thank you!
This is what I have so far:
// PrayerTimesCompanionApp.swift
// PrayerTimesCompanion Watch App
import SwiftUI
import WatchKit
@main
struct PrayerTimesCompanion_Watch_AppApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
.backgroundTask(.appRefresh("TIMINGS_REFRESH")) {
print("Found matching task")
scheduleNextBackgroundRefresh()
}
}
}
// Schedule the next background refresh
func scheduleNextBackgroundRefresh() {
let today = Calendar.current.startOfDay(for: .now)
if let tomorrow = Calendar.current.date(byAdding: .day, value: 1, to: today) {
WKApplication.shared().scheduleBackgroundRefresh(withPreferredDate: tomorrow, userInfo: "TIMINGS_REFRESH" as NSSecureCoding & NSObjectProtocol) { error in
if error != nil {
fatalError("*** An error occurred while scheduling the background refresh task. ***")
}
print("*** Scheduled! ***")
}
}
}
// ContentView.swift
// PrayerTimesCompanion Watch App
import SwiftUI
struct ContentView: View {
@StateObject var prayerTimeModel = PrayerTimesModel()
var body: some View {
List {
VStack {
VStack(spacing: 15) {
// Table Header
HStack {
Text("Prayer")
.bold()
.frame(maxWidth: .infinity, alignment: .leading) // Align to the left
Text("Iqamah")
.bold()
.frame(maxWidth: .infinity, alignment: .trailing) // Align to the right
}
.padding()
// Table Rows (5 prayers)
ForEach(prayerTimeModel.prayerTimes.data.iqamah, id: \.date) { iqamah in
rowView(prayer: "Fajr", time: iqamah.fajr)
rowView(prayer: "Zuhr", time: iqamah.zuhr)
rowView(prayer: "Asr", time: iqamah.asr)
rowView(prayer: "Maghrib", time: iqamah.maghrib)
rowView(prayer: "Isha", time: iqamah.isha)
}
}
.padding()
}
.padding()
.onAppear {
prayerTimeModel.fetch()
}
}
.edgesIgnoringSafeArea(.top)
}
func rowView(prayer: String, time: String) -> some View {
HStack {
Text(prayer)
.frame(maxWidth: .infinity, alignment: .leading)
Text(time)
.frame(maxWidth: .infinity, alignment: .trailing)
}
}
}
#Preview {
ContentView()
}
// PrayerTimesModel.swift
// PrayerTimesCompanion Watch App
import Foundation
import SwiftUI
// Main struct for the response
struct PrayerTimesResponse: Codable {
let status: String
var data: SalahData
let message: [String]
}
// Struct for the data section
struct SalahData: Codable {
var salah: [Salah]
var iqamah: [Iqamah]
}
// Struct for Salah times
struct Salah: Codable {
let date: String
let hijriDate: String
let hijriMonth: String
let day: String
var fajr: String
let sunrise: String
var zuhr: String
var asr: String
var maghrib: String
var isha: String
enum CodingKeys: String, CodingKey {
case date, hijriDate = "hijri_date", hijriMonth = "hijri_month", day, fajr, sunrise, zuhr, asr, maghrib, isha
}
}
// Struct for Iqamah times
struct Iqamah: Codable {
let date: String
var fajr: String
var zuhr: String
var asr: String
var maghrib: String
var isha: String
let jummah1: String
let jummah2: String
enum CodingKeys: String, CodingKey {
case date, fajr, zuhr, asr, maghrib, isha, jummah1 = "jummah1", jummah2 = "jummah2"
}
}
class PrayerTimesModel: ObservableObject {
@Published var prayerTimes: PrayerTimesResponse = PrayerTimesResponse(
status: "Unknown",
data: SalahData(
salah: [Salah(date: "", hijriDate: "", hijriMonth: "", day: "", fajr: "", sunrise: "", zuhr: "", asr: "", maghrib: "", isha: "")],
iqamah: [Iqamah(date: "", fajr: "", zuhr: "", asr: "", maghrib: "", isha: "", jummah1: "", jummah2: "")]),
message: ["No data available"]
)
// fetches the local mosque's prayer timings via an API call
func fetch() {
guard let url = URL(string: "https://masjidal.com/api/v1/time/range?masjid_id=3OA87VLp") else {
return
}
let task = URLSession.shared.dataTask(with: url) { [self] data, _, error in
guard let data = data, error == nil else {
return
}
// Convert to JSON
do {
var prayerTimes = try JSONDecoder().decode(PrayerTimesResponse.self, from: data)
DispatchQueue.main.async {
self.prayerTimes = prayerTimes
}
}
catch {
print(error)
}
}
task.resume()
}
}
What does it mean?
2.1.0 Performance: App Completeness
Guideline 2.1 - Performance - App Completeness
Submissions to App Review, including apps you make available for pre-order, should be final versions with all necessary metadata and fully functional URLs included; placeholder text, empty websites, and other temporary content should be scrubbed before submission. Make sure your app has been tested on-device for bugs and stability before you submit it, and include demo account info (and turn on your back-end service!) if your app includes a login. If you are unable to provide a demo account due to legal or security obligations, you may include a built-in demo mode in lieu of a demo account with prior approval by Apple. Ensure the demo mode exhibits your app’s full features and functionality. We will reject incomplete app bundles and binaries that crash or exhibit obvious technical problems.
Issue Description
The app exhibited one or more bugs that would negatively impact App Store users.
Bug description: your app displayed an error message when we used Sign in with Apple and did not proceed.
Review device details:
Device type: Apple Watch
OS version: watchOS 10.5
Next Steps
Test the app on supported devices to identify and resolve bugs and stability issues before submitting for review.
If the bug cannot be reproduced, try the following:
For new apps, uninstall all previous versions of the app from a device, then install and follow the steps to reproduce.
For app updates, install the new version as an update to the previous version, then follow the steps to reproduce.
Resources
For information about testing apps and preparing them for review, see Testing a Release Build.
To learn about troubleshooting networking issues, see Networking Overview.
Hello everyone,
I really need your help here :-))
iOS App. 17 and up. Widget extensions and watchOS app as well.
New build for iOS 18 earlier this week.
All platforms works perfect, except the Apple Watch version, which crash constantly on launch. Testing on simulator and testing devices - works perfect. Uploading to TestFlight and running on the same device - crash.
The only thing I see in the crash report is StoredLocationBased.get error. It takes me to nowhere inside the project.
Opened a DTS to Apple as well. Any help here will be fully appreciated.
Thank you so much!
Watch OS11 My recording play gets paused when watch I turned down.
It was not happening in previous versions.
In my app I recorded my recording.
And When I play it in my app,
it was playing good in debug mode(when Xcode is connected) could not debug.
Otherwise, it was automatically paused(when my wrist is down or inactivity time is elapsed)
I want it to be continued.
iOS 17.6.1 WatchOS 10.6.1
WatchAPP安装完毕之后,未登录,可以进入执行,提示 “未登录”
WatchAPP登录后,提示 “Apple Watch无法运行快捷指令,与App通信出现问题”
Info
watchOS: 11.0 (22R5348a) *Though has been present since watchOS 10.
Issue: Other apps playing music cancel out WKHaptics from firing (low volume and no vibrations)
Description
When another app is playing music (ex: spotify) in the background while using my app, that uses WKHaptics. The WKHaptics vibrations are non existent as long as headphones are connected.
When the headphones are disconnected the vibrations return.
Test
MVP test app >> https://github.com/mazefest/AppleCodeSupportTestApp
手表快捷指令,执行报错
Cannot send with an inactive account
I am probably being stupid but I can't find a way to code for the new 42mm/46mm series 10 watches.
I have downloaded the XCode RC and from what I remember from previous years with new screen sizes (Ultra, Series 7, Series 4 etc) that usually supports the new watches after they have been announced. However I can't see them in the simulator or as options in storyboards.
Do I need to download something else, or do I have to wait for a new version of XCode? Adjusting my app for new screen sizes is always time consuming and the new watches will be released in 10 days so I was hoping to make a start on it now.
I have an application with watchKit, now I am removing support to iWatch app. Is it possible that iWatch app will automatically disappear? Right now, it is not.
I am implementing apple wallet extension. As part of it I have developed UI and Non-UI extension. I have implemented status , pass entries and remote pass entries method to return as per apple standard. My problem is pass entries is showing correct list of cards/passes as it is able to match against phone wallet. But remote pass entries method is not able to access watch app/watch wallet to match the existing passes. Any help is appreciated. When we print passlibrary count it displays the count matching phone wallet. But it ignores watch wallet passes which belongs to our app.
Hello everyone, I’m currently developing an app for the Apple Watch and am working on implementing a dimming feature that activates when the device is in Theater mode.
Is there any way to detect programmatically whether Theater mode is enabled or disabled? Thanks!
After reading the documentation on .digitalCrownAccessory, I am under the impression that the system should know to show your accessory and hide your accessory according to whether the crown is being rotated. I have noticed this is not the case. I have also tried a few work arounds with no luck. Here is a simplified version of my code. I have recorded a video of the issue I am seeing, but I can't upload it, so I have attached some screenshots instead.
Expected result: After rotating the crown, the accessory image should disappear along with the vertical system scroll bar.
Actual result: After rotating the crown, the vertical system scroll bar disappears but the accessory image stays behind.
Versions:
Sonoma 14.6.1
Xcode 16 Beta 5 (and Xcode 15.4)
Apple Watch Ultra 2 watchOS 11 (device and simulator)
Starting file (main):
import SwiftUI
@main
struct DummyWatch_Watch_AppApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
ContentView.swift:
import SwiftUI
struct ContentView: View {
@State var crownValue: CGFloat = 0
var body: some View {
VStack {
Text("Hello, world!")
}
.focusable()
.digitalCrownRotation($crownValue,
from: 0,
through: 10,
by: 0.1,
sensitivity: .low,
isContinuous: false)
.digitalCrownAccessory {
Image(systemName: "speaker.fill")
}
.padding()
}
}
Images:
Scrolling:
Speaker wont go away:
Hi,
I have an app that provides a SmartStack Widget.
The content in that widget is dependent on a state inside the application so from time to time the app needs to update the widget state.
I tried:
WidgetCenter.shared.invalidateConfigurationRecommendations()
WidgetCenter.shared.reloadAllTimelines()
However this does not have any effect.
I only see updates on reboots (device with watchOS 11 B5)
Is there any other way or am I doing something wrong?