I've created a control centre widget modelled on the talk in "Extend your app's controls across the system".
In the talk, the user can select which timer they want to start ("work" or "violin").
The specific timer is passed to ToggleTimerIntent
as follows:
ControlWidgetToggle(
timerState.timer.name,
isOn: timerState.isRunning
action: ToggleTimerIntent(timer: timerState.timer)
) { isOn in
...
}
However, I can't find a way to access the timer
value from inside my ToggleTimerIntent
, since this code isn't provided in the talk.
An AppIntent must provide an empty init()
, so I've specified timer
as an option String:
@available(iOS 18, *)
struct ToggleTimerIntent: SetValueIntent {
static let title: LocalizedStringResource = "Toggle Timer"
// This value isn't never populated.
var timer: String?
@Parameter(title: "Running")
var value: Bool
func perform() async throws -> some IntentResult {
if let timer {
}
else {
// Always here
}
}
}
When I backtrace the code, ToggleTimerIntent
is instantiated several times, however perform()
is only called on an instance where the timer
value isn't provided.
Just to close the loop on this: when creating a widget extension, Xcode has a template to create this timer, which it does as follows:
struct StartTimerIntent: SetValueIntent {
static let title: LocalizedStringResource = "Start a timer"
@Parameter(title: "Timer Name")
var name: String
@Parameter(title: "Timer is running")
var value: Bool
init() {}
init(_ name: String) {
self.name = name
}
func perform() async throws -> some IntentResult {
// Start the timer…
return .result()
}
}
So anyway, the timer name needs to be marked as @Parameter
, and mustn't be optional.