I have a sports iOS app with a paired watch app, that uses location to update some UI elements. I technically need the location only when the watch app is in foreground, but since another requirement is to stop the clock from replacing the app, I decided to add background location checks. I followed the steps from the documentation (adding Background Modes to the watch extension target, setting allowsBackgroundLocationUpdates to true):
the location update works fine
when I go to the clock, the app's icon is displayed in a circle at the top (bringing the app back to foreground on tap).
The only problem is that the "Return to app" option in the "Return to Clock" settings menu is missing, what do I need to do in order to display it?
Here's an example of what it looks like for the Strava app:
and how it looks for mine.
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
132 Posts
Sort by:
Post
Replies
Boosts
Views
Activity
I'm showing several Steppers in a SwiftUI view on watchOS.
When the user taps the steppers & turns the digital crown it's possible to select multiple of the steppers (green "focus" border) appears.
I've tried to make the steppers mutually exclusive by using the following snippet, but it didn't work.
`@FocusState private var value: StepperType?`
[...]
var body: some View {
Form {
ForEach(StepperType.allCases, id: \.self) { stepperCase in
Stepper...
.focused($value, equals: stepperCase)
}
}
}
Any ideas how I can prevent multiple Steppers from being "focused" by the crown at the same time?
Does anyone have any idea why this is happening? It does this anywhere in my app where the keyboard is shown. I don't see any way I can be influencing how the keyboard is displayed so I am confused why this is happening and how to resolve it.
We created an app for iphone which includes a Watch app. The app works well during debugging, and also in TestFlight the Watch app installs nicely and does what it is supposed to do. However, when we make the app available through the Apple Business Manager (the app is for internal use by a company) the Iphone app downloads without problems, but the app for the Apple Watch does not work.
When I go to the Watch app on my Iphone (where you can manage the apps on your Watch and so on) my app is listed, but when I press install I see a loader for a few seconds, then it stops but nothing else happens.
So the code seems to be good, but after I download the app with a code through the Business Manager, then I cannot install the Watch version of the app.
When transferring files from iPhone to Watch, if you run the app and try to transfer after updating the OS, the transfer may not be possible. (or transmission seems to be too slow)
Just completely close the app, restart it, and try again.
Does anyone know the cause or solution to this problem?
It happened after the last 17.5 update and today after the 17.5.1 update.
The app doesn't crash or anything, and it doesn't happen often, so I didn't send any feedback or anything, but it's strange.
I'm trying to start and stop recording when my app is in background periodically. I implemented it using Timer and DispatchQueue. However whenever I am trying to initiate the recording I get this error. This issue does not exist in foreground.
Here is the current state of my app and configuration.
I have added "Background Modes" capability in the Signing & Capability and I also checked Audio and Self Care. Here is my Info.plist:
<plist version="1.0">
<dict>
<key>UIBackgroundModes</key>
<array>
<string>audio</string>
</array>
<key>WKBackgroundModes</key>
<array>
<string>self-care</string>
</array>
</dict>
</plist>
I also used the AVAudioSession with .record category and activated it. Here is the code snippet:
func startPeriodicMonitoring() {
let session = AVAudioSession.sharedInstance()
do {
try session.setCategory(AVAudioSession.Category.record, mode: .default, options: [.mixWithOthers])
try session.setActive(true, options: [])
print("Session Activated")
print(session)
// Start recording.
measurementTimer = Timer.scheduledTimer(withTimeInterval: measurementInterval, repeats: true) { _ in
self.startMonitoring()
DispatchQueue.main.asyncAfter(deadline: .now() + self.recordingDuration) {
self.stopMonitoring()
}
}
measurementTimer?.fire() // Start immediately
} catch let error {
print("Unable to set up the audio session: \(error.localizedDescription)")
}
}
Any thoughts on this? I have tried most of the ways but the issue is still there.
I have noticed that my Apple Watch app seems to randomly quit from time to time. It's not crashing and I have not been able to reproduce it in a controlled setting, but have noticed that it seems to only happen when I'm in very high or low temperatures. For instance, I was skiing recently and my app was supposed to stay running the whole time, but often when I would raise my wrist it would be back on the home screen and my app wasn't running. This also happened when I was on the beach on a very hot day. But when I'm testing it at home I can keep it running for hours and it never crashes, which leads me to believe it may have to do with the temperature. Does the OS kill apps when it's running in very high or low temperatures? If so, is there anything I can do to prevent this from occurring?
Would doing less things in my app possibly prevent this? For instance, I have a timer, and use a bunch of sensors, would turning those off at times and using less of the display make a difference or does the OS not care what the apps are actually doing? If not, any other ideas?
Thanks
Long story short, I had my App and Watch app already uploaded to the app store. However, I needed to add a WatchConnectivity to have App to Watch communication.
At the beginning My app bundle id was: com.x My watch bundle id was: com.x.watchkitapp
However, while developing Watch Connectivity, I noticed that my Apps are not connected unless I changed it to com.x.watchkitapp -> com.x.watch
However after changing it I cannot submit my bundle anymore.
I'm getting Asset validation failed error
Invalid Bundle Identifier. Attempting to change bundle identifier from com.x.watchkitapp to com.x.watch is disallowed for bundle x.app/Watch/WatchX Watch App.app. (ID: 75a4621a-7e28-411d-a2a7-84674e460656)
Any ideas how this could be solved?
After updating to iOS 17.5 & WatchOS 10.5, the didFinish response from WCSessionDelegate does not come when transferring files from iPhone to Watch.
It worked normally until 17.4 & 10.4.
There is no problem with checking file completion even if a didFinish response is not received, but I think Apple needs to check this issue and update.
File transfer is done using the transferFile function of WCSession.
The file being transferred is a single file and its size does not exceed 30MB.
When you try to transfer Pi, the message below appears in the Xcode log section.
-[WCFileStorage persistOutgoingFileTransfer:] error serializing file transfer <WCSessionFileTransfer: 0x300155d60, session file: <WCSessionFile: 0x3001575c0, identifier: 0C8857EC-7D74-4E78-BA28-6C5526DE8949, file: /private/var/mobile/Containers/Data/Application/DD797847-DED1-42C0-989F-34CD05825007/tmp/C042D096-F12B-4B50-8792-868475DBBF47.zip, hasMetadata: YES>, transferring: YES> due to Error Domain=NSCocoaErrorDomain Code=4866 "Caught exception during archival: This object may only be encoded by an NSXPCCoder.
(
0 CoreFoundation 0x000000019b064f2c 00E76A98-210C-3CB5-930B-F236807FF24C + 540460
1 libobjc.A.dylib 0x0000000192ef6018 objc_exception_throw + 60
2 Foundation 0x0000000199fe7778 3D3A12E3-F5E9-361F-B00A-4A5E8861AA55 + 1419128
3 Foundation 0x0000000199ea0e14 3D3A12E3-F5E9-361F-B00A-4A5E8861AA55 + 81428
4 WatchConnectivity 0x000000021d055f60 1AB4DDD6-9238-3965-B744-819F2916C8CC + 126816
5 Foundation 0x0000000199ea0e14 3D3A12E3-F5E9-361F-B00A-4A5E8861AA55 + 81428
6 WatchConnectivity 0x000000021d0567f0 1AB4DDD6-9238-3965-B744-819F2916C8CC + 129008
7 Foundation 0x0000000199ea0e14 3D3A12E3-F5E9-361F-B00A-4A5E8861AA55 + 81428
8 Foundation 0x0000000199f30628 3D3A12E3-F5E9-361F-B00A-4A5E8861AA55 + 669224
9 WatchConnectivity 0x000000021d0583ac 1AB4DDD6-9238-3965-B744-819F2916C8CC + 136108
10 WatchConnectivity 0x000000021d04390c 1AB4DDD6-9238-3965-B744-819F2916C8CC + 51468
11 WatchConnectivity 0x000000021d046640 1AB4DDD6-9238-3965-B744-819F2916C8CC + 63040
12 Foundation 0x0000000199ea9be0 3D3A12E3-F5E9-361F-B00A-4A5E8861AA55 + 117728
13 Foundation 0x0000000199ea9aa0 3D3A12E3-F5E9-361F-B00A-4A5E8861AA55 + 117408
14 Foundation 0x0000000199ea98a0 3D3A12E3-F5E9-361F-B00A-4A5E8861AA55 + 116896
15 Foundation 0x0000000199ea7b40 3D3A12E3-F5E9-361F-B00A-4A5E8861AA55 + 109376
16 Foundation 0x0000000199f2c558 3D3A12E3-F5E9-361F-B00A-4A5E8861AA55 + 652632
17 Foundation 0x0000000199f2c1a4 3D3A12E3-F5E9-361F-B00A-4A5E8861AA55 + 651684
18 libdispatch.dylib 0x0000000105ed7764 _dispatch_block_async_invoke2 + 148
19 libdispatch.dylib 0x0000000105ec67bc _dispatch_client_callout + 20
20 libdispatch.dylib 0x0000000105ec98e0 _dispatch_continuation_pop + 676
21 libdispatch.dylib 0x0000000105ec8bb8 _dispatch_async_redirect_invoke + 680
22 libdispatch.dylib 0x0000000105edaae4 _dispatch_root_queue_drain + 404
23 libdispatch.dylib 0x0000000105edb4d8 _dispatch_worker_thread2 + 188
24 libsystem_pthread.dylib 0x00000001f7ebb8f8 _pthread_wqthread + 228
25 libsystem_pthread.dylib 0x00000001f7eb80cc start_wqthread + 8
)" UserInfo={NSDebugDescription=Caught exception during archival: This object may only be encoded by an NSXPCCoder.
(
0 CoreFoundation 0x000000019b064f2c 00E76A98-210C-3CB5-930B-F236807FF24C + 540460
1 libobjc.A.dylib 0x0000000192ef6018 objc_exception_throw + 60
2 Foundation 0x0000000199fe7778 3D3A12E3-F5E9-361F-B00A-4A5E8861AA55 + 1419128
3 Foundation 0x0000000199ea0e14 3D3A12E3-F5E9-361F-B00A-4A5E8861AA55 + 81428
4 WatchConnectivity 0x000000021d055f60 1AB4DDD6-9238-3965-B744-819F2916C8CC + 126816
5 Foundation 0x0000000199ea0e14 3D3A12E3-F5E9-361F-B00A-4A5E8861AA55 + 81428
6 WatchConnectivity 0x000000021d0567f0 1AB4DDD6-9238-3965-B744-819F2916C8CC + 129008
7 Foundation 0x0000000199ea0e14 3D3A12E3-F5E9-361F-B00A-4A5E8861AA55 + 81428
8 Foundation 0x0000000199f30628 3D3A12E3-F5E9-361F-B00A-4A5E8861AA55 + 669224
9 WatchConnectivity 0x000000021d0583ac 1AB4DDD6-9238-3965-B744-819F2916C8CC + 136108
10 WatchConnectivity 0x000000021d04390c 1AB4DDD6-9238-3965-B744-819F2916C8CC + 51468
11 WatchConnectivity 0x000000021d046640 1AB4DDD6-9238-3965-B744-819F2916C8CC + 63040
12 Foundation 0x0000000199ea9be0 3D3A12E3-F5E9-361F-B00A-4A5E8861AA55 + 117728
13 Foundation 0x0000000199ea9aa0 3D3A12E3-F5E9-361F-B00A-4A5E8861AA55 + 117408
14 Foundation 0x0000000199ea98a0 3D3A12E3-F5E9-361F-B00A-4A5E8861AA55 + 116896
15 Foundation 0x0000000199ea7b40 3D3A12E3-F5E9-361F-B00A-4A5E8861AA55 + 109376
16 Foundation 0x0000000199f2c558 3D3A12E3-F5E9-361F-B00A-4A5E8861AA55 + 652632
17 Foundation 0x0000000199f2c1a4 3D3A12E3-F5E9-361F-B00A-4A5E8861AA55 + 651684
18 libdispatch.dylib 0x0000000105ed7764 _dispatch_block_async_invoke2 + 148
19 libdispatch.dylib 0x0000000105ec67bc _dispatch_client_callout + 20
20 libdispatch.dylib 0x0000000105ec98e0 _dispatch_continuation_pop + 676
21 libdispatch.dylib 0x0000000105ec8bb8 _dispatch_async_redirect_invoke + 680
22 libdispatch.dylib 0x0000000105edaae4 _dispatch_root_queue_drain + 404
23 libdispatch.dylib 0x0000000105edb4d8 _dispatch_worker_thread2 + 188
24 libsystem_pthread.dylib 0x00000001f7ebb8f8 _pthread_wqthread + 228
25 libsystem_pthread.dylib 0x00000001f7eb80cc start_wqthread + 8
)}
As TN3135 clearly explains the limitations apple puts on the low level networking, it doesn’t really give a reason. Presumably the power consumption problem. But as the battery technology continues evolving, it could be exciting that apple might loose the restrictions someday. The watch itself is powerful enough to do a lot of sophisticated works, sure it works best with companion apps on iPhone, but even as a standalone device, we can still provide many advanced user experience with low level networking supports.
wish apple guys can read it and give a consideration.
I am running two different background modes(not at the same time), 1 with a workout and 1 with a location. I noticed that the app logo appears above the watch face for both background modes but does not show up consistently. I wonder what the significance of the logo showing up above watch face is? Additionally why does it show up sometimes but not others?
Thanks
On android there is a way for my app to know when the device has been restarted or powered up after a restart or powering off. I wonder if there is a way to listen for the restart/power up even on the iphone and the Apple Watch?
Hi,
I would like to stream live audio (hls) from watch itself, our app can start stream on paired device, but when phone is not near by i want to start streaming on watchos (just like spotify or Apple music app) I watched the 2019 wwdc video about streaming and also looked to the documentation
Documentation : https://developer.apple.com/documentation/watchkit/storyboard_support/playing_background_audio
I can present the route controller to select output, but for example after selecting Air Podcas, stream did not start..
Here is the code: (I have enabled background mode audio)
do {
try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default, policy: .longFormAudio, options: [])
}
catch {
print("no audiosession!")
}
AVAudioSession.sharedInstance().activate(options: []) { success, error in
dump(success)
dump(error)
DispatchQueue.main.async {
if let streamURL = moduleItem.media?[0] as? String {
dump(streamURL)
let asset = AVURLAsset(url: URL(string: streamURL)!, options: nil)
let item = AVPlayerItem(asset: asset)
let player = AVQueuePlayer(playerItem: item)
player.play()
}
}
}
I noticied that my workout session is sometimes being killed by apple when the app is in the background and it seems that the func workoutSession(_ workoutSession: HKWorkoutSession, didChangeTo toState: HKWorkoutSessionState, from fromState: HKWorkoutSessionState, date: Date) {
is only being called when the app comes back into the foreground.
I wonder if there is a way for us to get notified when the workout is about to die or has already been killed.
Thanks
如何自定义开发表盘模版,不是表盘组件,比如设置背景图片,调整各个表盘组件的位置
手表系统: 10.2
表现:从手机Watch App上看,表盘组件部分都显示关闭;从手表上看,表盘组件不展示
Hello Apple Developer Forum,
I'm reaching out because I've encountered an issue with my app's implementation involving the ScrollView and the digitalCrown, and I'm hoping to find some guidance or assistance from the community.
Currently, I'm developing an app where users can navigate through dates using the digitalCrown to change the "$scrollAmount", which then dynamically updates the ScrollView with events corresponding to that date. However, I've run into a problem where the ScrollView is being inadvertently scrolled by the digitalCrown every time it's initiated.
Ideally, I would like to disable the digitalCrown's interaction with the ScrollView altogether, so that the ScrollView is only scrolled using touch inputs and not by the digitalCrown. I've tried several approaches to achieve this, but haven't had much success so far.
Could anyone please provide some guidance or suggestions on how I can effectively disable the digitalCrown's interaction with the ScrollView while still allowing touch-based scrolling?
Any help or insights into this matter would be greatly appreciated. Thank you very much in advance for your time and assistance.
Best regards,
Example code:
var body: some View {
NavigationView {
VStack {
HStack{
Text("\(formattedDate(for: scrollAmount, format: lineOne))")
.onTapGesture {
scrollAmount = 0.0
}
}
ScrollView{
ForEach(viewModel.events, id: \.event) { viewModelItem in
let event = viewModelItem.event
VStack {
HStack {
Text(event.title)
}
}
}
}
.scrollDisabled(true)
}
}
.focusable(isFocused)
.digitalCrownRotation(
detent: $scrollAmount,
from: -365.0,
through: 365.0,
by: 1.0,
sensitivity: .low,
isContinuous: false,
isHapticFeedbackEnabled: true)
.onChange(of: scrollAmount) {
let roundedValue = round(scrollAmount)
scrollAmount = roundedValue
viewModel.fetchEvents(for: scrollAmount)
}
}
}
Hi,
I'm triggering a notification from the audio interruption handler (but also have a debug button set to trigger it manually) and it frequently does not show up. I don't think I have ever seen it show up when the watch face is off.
I have created a singleton class to trigger this notification as follows. Note that I use a UUID in the identifier because an old thread here suggests this is necessary, but it makes no difference as far as I can tell.
Any ideas? I'd like this notification to be reliable. I'm also surprised that with trigger set to nil, it does not trigger instantaneously.
Any help would be much appreciated!
Thanks,
-- B.
import Foundation
import UserNotifications
class NotificationSender: NSObject, UNUserNotificationCenterDelegate {
static let shared = NotificationSender()
override init() {
super.init()
let center = UNUserNotificationCenter.current()
center.requestAuthorization(options: [.sound, .badge]) { granted, error in
if granted {
print("Notification permission granted")
} else {
print("Notification permission denied")
}
}
center.delegate = self
// Define the action to open the app
let openAction = UNNotificationAction(identifier: "openAction", title: "Open App", options: [.foreground])
// Add the action to the notification content
let category = UNNotificationCategory(identifier: "resumeAudioCategory", actions: [openAction], intentIdentifiers: [], options: [])
center.setNotificationCategories([category])
}
func sendNotification() {
let center = UNUserNotificationCenter.current()
let content = UNMutableNotificationContent()
content.title = "Recording Interrupted"
content.body = "You will need to restart it manually."
content.categoryIdentifier = "resumeAudioCategory"
// Create the notification request
//let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: false)
let request = UNNotificationRequest(identifier: "ResumeAudioNotification-\(UUID().uuidString)", content: content, trigger: nil)
center.add(request) { error in
if let error = error {
print("Error adding notification request: \(error)")
}
}
}
// Handle notification when the app is in the foreground
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
// Display the notification while the app is in the foreground
completionHandler([.sound, .badge, .banner, .list])
}
// Handle notification response
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
// Handle the user's response to the notification
// For example, navigate to a specific screen in your app
completionHandler()
}
}
I am developing an AppleWatch applet. There is no IOS side, only the Apple Watch side. I want to evoke SIRI on the Apple Watch, then say "Open my software" or a specific sentence, and then my software will be automatically opened.
I am a watchOS 10.0 device, try to open the developer mode, according to the official website to enter the Settings > Privacy > Developer Mode. But I don't see the developer mode option, how do I turn on the developer mode for watchOS 10.0 device?