Explore enhancements to App Intents

RSS for tag

Discuss the WWDC23 Session Explore enhancements to App Intents

View Session

Posts under wwdc2023-10103 tag

19 Posts
Sort by:
Post not yet marked as solved
11 Replies
2.2k Views
Hi, I am trying to integrate the new AppIntentsPackage protocol into my application. Especially what I want to do is to create a dedicate SPM package which holds all my app intents and then share that with my widget extension for Widget intents as well as the main iOS app for powering an AppShortcutProvider. Unfortunately I run into an issue here. I have the following explanatory setup: SPM package called ProjectAppIntents iOS target My AppIntents SPM package //Package: ProjectAppIntents public struct TestAppIntent: AppIntent { public static var title: LocalizedStringResource = "TestAppIntent" @Parameter(title: "Parameter1", optionsProvider: ParameterOptionProvider()) public var parameter: String public init(parameter: String) { self.parameter = parameter } public init() { } public func perform() async throws -> some IntentResult & ReturnsValue { .result(value: 5) } } struct ParameterOptionProvider: DynamicOptionsProvider { func results() async throws -> [String] { return ["Hello", "World"] } } public struct ProjectAppIntentsPackage: AppIntentsPackage { } My iOS app // Target: iOS import ProjectAppIntents struct ProjectApp: App { var body: some Scene { WindowGroup { ContentView() } } } extension ProjectApp: AppIntentsPackage { static var includedPackages: [AppIntentsPackage.Type] = [ ProjectAppIntentsPackage.self ] } struct ProjectShortcuts: AppShortcutsProvider { static var appShortcuts: [AppShortcut] { AppShortcut( intent: TestAppIntent(), phrases: ["Start a \(.applicationName)"], shortTitle: "Hello World", systemImageName: "house" ) } } When I now try to compile my app, I get the following build error: 2023-06-25 09:53:47.853 appintentsnltrainingprocessor[44848:2059163] Parsing options for appintentsnltrainingprocessor 2023-06-25 09:53:47.854 appintentsnltrainingprocessor[44848:2059163] Starting AppIntents SSU YAML Generation 2023-06-25 09:53:47.868 appintentsnltrainingprocessor[44848:2059163] error: The action TestAppIntent referenced in App Shortcut does not exist Command AppIntentsSSUTraining failed with a nonzero exit code So for me it seems like the compiler cannot find the AppIntent defined in an SPM package. Am I doing something wrong here or does the AppIntentsPackage protocol not work with SPM packages ? Thanks a lot for helping !
Posted Last updated
.
Post not yet marked as solved
1 Replies
646 Views
I am trying to implement App Shortcuts for my app. I want to implement the same as Books. I am trying to do 2 things. I want to set a custom image for each App Shortcut. I want to set custom color for the Shortcuts background like orange in the Books App Shortcuts. I am trying to implement in iOS 16. Kindly share your ideas. If at all possible, kindly share a snippet
Posted Last updated
.
Post not yet marked as solved
0 Replies
410 Views
Was watching this latest WWDC 2023 video and had a question. I see about 17:20 in, they mention you can now put the shortcut provider in an app intent extension. https://developer.apple.com/videos/play/wwdc2023/10103/ This works fine by itself and I can see all my shortcuts and use siri, but as soon as I try to call into the extension from the main app in order to trigger updateAppShortcutParameters() or any other code, I get a linker error. Am I doing something obvious wrong? Note, I called it a framework, but it Is just an extension. Cant figure out how I am supposed to be calling this method. Any help is greatly appreciated! https://developer.apple.com/documentation/appintents/appshortcutsprovider/updateappshortcutparameters()?changes=_4_8 https://imgur.com/a/yDygSVJ
Posted Last updated
.
Post not yet marked as solved
5 Replies
1.7k Views
I have AppIntent code which lives in my app package that can not easily be decoupled and migrated into its own standalone framework or extension. This is because this intent has some action that relies on my app's network and core data stack. I'd like to expose this existing intent in some way to a Button in a widget, but so far I have not had success. Is this currently possible with AppIntentPackage or some other means? Is there a way I can use AppIntents to pass a message back to the app? How should I approach this? Thank you!
Posted
by reed.1325.
Last updated
.
Post not yet marked as solved
0 Replies
408 Views
As you can see in the following screenshot the „Water“ selection is an AppEnum which gets a nicely tinted SF Symbol. On the other hand, the „My Home“ is an AppEntity which also uses an SF Symbol, but doesn’t get the blue tint. Why? Now my question is, how can I force the tint on the AppEntity as well? I’ve defined it the following way: var displayRepresentation: DisplayRepresentation { DisplayRepresentation( title: "\(title)", image: .init(systemName: "house", isTemplate: true) ) } But even adding the isTemplate doesn’t work here …
Posted Last updated
.
Post not yet marked as solved
0 Replies
376 Views
I have a SiriKit type in intent definition which include system field 'identifier' and a custom field id. When I try to migrate to AppIntent, since AppEntity conforms to 'Identifiable' I cannot use 'id' in AppEntity, how can I solve this?
Posted
by eyvallah.
Last updated
.
Post not yet marked as solved
1 Replies
696 Views
AppIntent of the same type is created both for main and widget targets. If app is launched in background, built-in main target intent is executed, but if app is closed, then app is not launched in background mode to execute built-in intent. Is it supposed to be like this or is it a bug?
Posted Last updated
.
Post marked as solved
1 Replies
569 Views
I’m implementing App Shortcuts in my iOS app to allow you to add and find plants. In attempt to get a “Find Plants” shortcut, I created a query that conforms to EnumerableEntityQuery and set that as the defaultQuery in my PlantAppEntity. I have the typeDisplayRepresentation set to TypeDisplayRepresentation(name: "Plant", numericFormat: "\(placeholder: .int) plants"). I added a Localizable.stringsdict to the app target, added Plant and %lld plants as the header comments shows, then clicked Localize so now English is selected in the Localization section. But when I run the app then open Shortcuts and tap my app, there’s a Find Plant shortcut, but I expected it to be titled Find Plants. When I tap the info button it shows “plant” instead of “plants” in every parameter description. When you add that action to a shortcut the placeholder is All Plant, unlike similar shortcuts from Reminders and Contacts that say “All Reminders” and “All Contacts”. The action is working properly as it returns an array of plants, the only issue is it’s using the singular form of plant in places it should be plural. Have I done something wrong, am I missing anything, or is this a bug? (FB12908309)
Posted
by Jordan.
Last updated
.
Post not yet marked as solved
1 Replies
563 Views
I tried to add iOS 17 version check inside WidgetBundle but the widget extension keep on crashing . Getting Thread 1: Swift runtime failure: Unexpectedly found nil while unwrapping an Optional value. After removing the iOS 17 check it works fine. Is there any way to provide version check inside widgetBundle?
Posted Last updated
.
Post not yet marked as solved
3 Replies
726 Views
In Xcode 15 beta 3 and beta 4, if you add a AppShortcuts.xcstrings catalog or legacy AppShortcuts.strings files to the project, the project will always fail to build due to the following error. error: Unable to call validation: The data couldn’t be read because it isn’t in the correct format. (in target 'LearnAppShortcuts' from project 'LearnAppShortcuts') Command ValidateAppShortcutStringsMetadata emitted errors but did not return a nonzero exit code to indicate failure The error seems related to a cli called ValidateAppShortcutStringsMetadata. Reproducing Steps (1) In Xcode 15 beta 3/4, create a new iOS app project. (2) Add an arbitrary AppIntent and AppShortcutsProvider. import AppIntents struct MyAction: AppIntent { static let title: LocalizedStringResource = "My Action" func perform() async throws -> some IntentResult { return .result() } } struct MyAppShortcts: AppShortcutsProvider { static var appShortcuts: [AppShortcut] { AppShortcut(intent: MyAction(), phrases: [ "Perform action with \(.applicationName)" ], shortTitle: "Perform My Action", systemImageName: "heart") } } (3) Create a new AppShortcuts.xcstrings catalog file and add it to the iOS target (4) Build the project. The string catalog will be updated as expected. However, the build will fail.
Posted
by Gong.
Last updated
.
Post not yet marked as solved
0 Replies
532 Views
Hi there, I'm adding a new widget using the new WidgetConfigurationIntent which takes a number of parameters, including one which conforms to AppEntity. It is defined as an optional. When the user is configuring the widget, after one of the suggested entities is chosen, there is no way to return to a state where this value is nil. Is this possible? I'd like the user to be able to select "None" for this parameter. For now, I'm using a bool to determine whether the AppEntity parameter is used. Thanks!
Posted Last updated
.
Post not yet marked as solved
0 Replies
382 Views
Do watchOS Complications support interactivity via App Intents? I see that the Button initializer IS supported on watchOS, but any widget I try this on only seems to open the watch app.
Posted Last updated
.
Post not yet marked as solved
0 Replies
601 Views
This is Siri Intent before iOS 16. func handle(intent: CustomIntent, completion: @escaping (CustomIntentResponse) -> Void) { completion(CustomIntentResponse(code: .continueInApp, userActivity: nil)) } This flow working fine. This is AppIntent after iOS 16. There are 2 ways to continue in app openAppWhenRun = true ForegroundContinuableIntent Protocol only works in SwiftUI But both are not notifying the main app its just opening app without activity. In SiriIntent we can notifiy Main App with completion(CustomIntentResponse(code: .continueInApp, userActivity: nil)) application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool else its start with didfinishlaunching and we can get useractivity. Is there any solution for after iOS 16 In AppIntent we can notify app and get NSUserActivity?
Posted Last updated
.
Post not yet marked as solved
1 Replies
655 Views
I'm running into a couple of breaking issues with AppIntents for which I just submitted feedbacks. I figured I'd post them on the forum too for good measure. FB12701143 - @IntentParameterDependency causing crashes in all AppIntents with Entity Queries on iOS 16 I have a pre-existing AppIntent with its own EntityQuery that works just fine on iOS 16. I've built a totally separate intent only available in iOS 17 that makes use of a new entity and a new query using @IntentParameterDependency, but now the original intent crashes after building and running the app on an iOS 16 device with the latest Xcode beta. The line it crashes on is the initializer of the iOS 17-only EntityQuery, even though 1) it shouldn't be able to see it and 2) that EntityQuery isn't involved in the crashing intent. This breaks significant functionality in my AppIntents, and I'm hoping this is a bug rather than a framework limitation. The feedback includes a sample project, crash log, and sysdiagnose. FB12701491 - iOS 17-only CustomIntentMigratedAppIntent stops SiriKit intent equivalent from working on iOS 16 I have a SiriKit intent in my app that I was not able to convert to an AppIntent until iOS 17 because it makes use of an @IntentParameterDependency. However, even though the new AppIntent version is marked as only available in iOS 17 and above, once I conform it to CustomIntentMigratedAppIntent and provide the old intent’s class name, it stops working on iOS 16 devices with an error that the shortcut is unavailable on that device. The CustomIntentMigratedAppIntent should respect the iOS 17 availability annotation and leave the SiriKit intent alone since its migrated replacement isn’t available on iOS 16. The feedback includes a sample project illustrating the issue.
Posted Last updated
.
Post not yet marked as solved
1 Replies
864 Views
I'm playing around with Interactive Widgets and I am trying to make one that starts playing audio content without bringing the app to the foreground. The new Button used in interactive widgets accepts an AppIntent, but INPlayMediaIntent doesn't conform to AppIntent. Starting to play something directly from an AppIntent doesn't seem to work either. The system kills my process if I try to call the following from an AppIntent: ''' try! AVAudioSession.sharedInstance().setActive(true) '''
Posted
by JagCesar2.
Last updated
.
Post not yet marked as solved
0 Replies
871 Views
Hello! I'm trying to donate an Intent to iOS using IntentDonationManager, following the methods described in the documentaion. try await IntentDonationManager.shared.donate(intent: MyIntent()) // succeeded However, I'm not seeing any effect of this action anywhere in the system (iOS 17 and 16). I have debugged it on both the simulator and a physical device, and I have also enabled the "Display Recent Shortcuts" toggle in the developer settings, but I still don't see any relevant suggestions appearing. Similarly, the issue also occurs with the old SiriKit framework, where INInteraction.donate(completion:) doesn't seem to have any observable effect. I recall that in iOS 15, the simulator would immediately present the donated Shortcut action on the lock screen and Spotlight page. However, starting from iOS 16 and continuing to the current iOS 17 beta 1/2, I haven't been able to achieve the same behavior using the same code. Another similar report: https://developer.apple.com/forums/thread/723109 So is there any way to test or verify the results of this donation action?
Posted
by Gong.
Last updated
.
Post not yet marked as solved
0 Replies
691 Views
We have an AppIntent that starts streaming data in its perform() function with a URLSession. This may be a quick operation, or it may take some time (more than 30 seconds but less than a minute). Is there any way we can keep that streaming data URLSession active when the AppIntent asks the user to continue with requestConfirmation? What we have seen so far is that any operation the AppIntent takes in its perform() function that interacts with the user causes the URLSession to be abruptly terminated with a NSURLErrorNetworkConnectionLost error when the app is not in the foreground. If the app is currently running in the foreground then the session does remain active and data continues to stream in. Sadly, our primary use case is for the Siri/Shortcuts interaction to happen with openAppWhenRun set to false and not require the user to open the app. In that case (with the AppIntent invoked while the app is in the background) the network connection is dropped. It has been frustrating in initial development because on the simulator the connection is not dropped and data continues to stream in, even while the app is in the background. On a physical device, this is not the case. The only condition we have found to have the network connection maintained is with the app in the foreground when the AppIntent is run. Here is what we have now: struct AskAI: AppIntent { static var title: LocalizedStringResource = "Ask" static var description: IntentDescription = IntentDescription("This will ask the A.I. app") static var openAppWhenRun = false @Parameter(title: "Prompt", description: "The prompt to send", requestValueDialog: IntentDialog("What would you like to ask?")) var prompt: String @MainActor func perform() async throws -> some IntentResult & ProvidesDialog & ShowsSnippetView & ReturnsValue<String> { var continuationCalled = false //Start the streaming data URLSession task Task<String, Never> { await withCheckedContinuation { continuation in Brain.shared.requestIntentStream(prompt: prompt, model: Brain.shared.appSettings.textModel, timeoutInterval: TimeInterval(Brain.shared.appSettings.requestTimeout )) { result in if !continuationCalled { continuationCalled = true continuation.resume(returning: Brain.stripMarkdown(result)) } } } } //Start the intentTimeout timer and early out if continuationCalled changed let startTime = Date() let timeout = Brain.shared.appSettings.intentTimeout while !continuationCalled && Date().timeIntervalSince(startTime) < timeout { try? await Task.sleep(nanoseconds: 1_000_000_000) } //At this point either the intentTimeout was reached (data still streaming) or continuationCalled is true (data stream complete) //best effort for Siri to read the first part and continue as more is received var allReadResponse = "" var partialResponse = "" while !continuationCalled { partialResponse = Brain.shared.responseText.replacingOccurrences(of: allReadResponse, with: "") allReadResponse += partialResponse do { let dialogResponse = partialResponse + " --- There is more, would you like to continue?" //THIS WILL TERMINATE THE URLSession if the app is not in the foreground! try await requestConfirmation(result: .result(dialog: "\(dialogResponse)") { AISnippetView() }) } catch { return .result( value: Brain.shared.responseText, dialog: "", //user cancelled, return what we have so far but we've already spoken the dialog view: AISnippetView() ) } } //Read the last part (or the whole thing it it was retrieved within the intentTimeout) let remainingResponse = Brain.shared.responseText.replacingOccurrences(of: allReadResponse, with: "") return .result( value: Brain.shared.responseText, dialog: "\(remainingResponse)", view: AISnippetView() ) } } With this logic, Siri will read the first part of the response data when the timer expires and continuationCalled is false. The data is still streaming and will continue to come in while she is speaking - ONLY IF THE APP IS IN THE FOREGROUND. Otherwise the call to requestConfirmation will terminate the connection. Is there any way to get the task with the requestIntentStream URLSession to stay active?
Posted Last updated
.