The workaround I ended up with was this:
- Wrap the
WKInterfaceVolumeControl
to use it in SwiftUI
struct VolumeView: WKInterfaceObjectRepresentable {
typealias WKInterfaceObjectType = WKInterfaceVolumeControl
func makeWKInterfaceObject(context: Self.Context) -> WKInterfaceVolumeControl {
let view = WKInterfaceVolumeControl(origin: .local)
Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { [weak view] timer in
if let view = view {
view.focus()
} else {
timer.invalidate()
}
}
DispatchQueue.main.async {
view.focus()
}
return view
}
func updateWKInterfaceObject(_ wkInterfaceObject: WKInterfaceVolumeControl, context: WKInterfaceObjectRepresentableContext<VolumeView>) {
}
}
- Add the
VolumeView
to the view hierarchy with opacity = 0
.
.background(VolumeView().opacity(0))
- Listen to volume updates from the system.
volumeObserver = AVAudioSession.sharedInstance().observe(\.outputVolume) { session, _ in
print("Output volume: \(session.outputVolume)")
self.volume = Double(session.outputVolume)
}
With that you can update some other view, but keep in mind that especially on older what's the update does not always happen (immediately).
WKInterfaceVolumeControl
throughWKInterfaceObjectRepresentable
to the View hierarchy and settings itsopacity
to0
. You have to make sure that the volume control keeps the focus. I added a repeating timer where I set the focus, just to be sure. Then then observeAVAudioSession.sharedInstance().observe(\.outputVolume)
and update a smaller view in code. This works ok... On my older watch there is quite a lack between the volume changing and the app getting the volume update. But I think it is the only way to control the volume without the big control. – Valentine