Share intents from within an app to drive system intelligence and show the app's actions in the Shortcuts app.

Posts under Intents tag

58 Posts
Sort by:
Post not yet marked as solved
1 Replies
414 Views
I haven’t done any work for Intents so I don’t know why iOS is making Siri suggestions for my app. Every now and then, maybe especially in the morning, my iPhone will show a button at the bottom of the Lock Screen with my app icon, the title of a data record from inside my app, and the caption “Siri suggestion”. Tapping it launches my app but that’s it. The app doesn’t show the record. Why is iOS doing this? Is this some half-baked effect of using iCloud data or Swift Data? I can’t release the app with iOS doing this, and adding proper Intent support would delay the release.
Posted
by
Post not yet marked as solved
0 Replies
351 Views
Hello, I have a question regarding app Intents. I have a simple App Intent and it is working as expected (I can see it in shortcuts and the action shows a phrase and opens my app). I would now want to ask the user for an "App" parameter, that would be any app the user has downloaded on his iPhone. Here my example intent: struct SayPhraseIntent: AppIntent { static var title: LocalizedStringResource = "See a text." static var description = IntentDescription("Just says whatever text you type in.") @Parameter(title: "Text") var text: String? func perform() async throws -> some ProvidesDialog { guard let providedText = text else { throw $phrase.needsValueError("What text do you want to see?") } return .result(dialog: IntentDialog(stringLiteral: providedText)) } } An example of a shortcut that asks this is I have seen some apps do it so it must be possible, but I cannot find anywhere the Type of the @Parameter I would need to get that from a user through the shortcut app. Any help or suggestions would be appreciated.
Posted
by
Post not yet marked as solved
0 Replies
326 Views
Hi, I have an app that is used by several Shortcuts. In many cases, users download the Shortcut, install the app, and only use the App through the Shortcut, and only through the in-extension Intent. They might never open the app. I've received complaints from users that the app keeps disappearing: apparently, because the app itself is never opened (only the in-extension Intent is), it doesn't count as an actual usage for offloading, and so the app gets offloaded. What can I do?
Posted
by
Post not yet marked as solved
0 Replies
465 Views
I am developing an app for my home and I was planning to control my smart home plug with it. So I decided to create two shortcuts: the first one to turn it on, the second one to turn it off. For this, I created an AppIntent and an AppShortcut file: // AppIntent.swift // Runner import AppIntents import Foundation class MerossPostClass{ var request: URLRequest var power_state: String public init(power_state: String) { self.power_state = power_state let url = URL(string: "myurl")! var request = URLRequest(url: url) request.httpMethod = "POST" struct Message: Encodable { let device_type: String let power_state: String let channel: Int } let message = Message( device_type: "mss425f", power_state: power_state, channel: 4 ) let data = try! JSONEncoder().encode(message) request.httpBody = data request.setValue( "application/json", forHTTPHeaderField: "Content-Type" ) self.request = request } public func post(){ let task = URLSession.shared.dataTask(with: self.request) { data, response, error in let statusCode = (response as! HTTPURLResponse).statusCode if statusCode == 200 { print("SUCCESS") } else { print("FAILURE") } } task.resume() } } var activateMeross = MerossPostClass(power_state: "ON") var deactivateMeross = MerossPostClass(power_state: "OFF") @available(iOS 17, *) struct ActivateMagSafeIntent: AppIntent { static let title: LocalizedStringResource = "Activate MagSafe" func perform() async throws -> some IntentResult { activateMeross.post() return .result() } } @available(iOS 17, *) struct DeactivateMagSafeIntent: AppIntent { static let title: LocalizedStringResource = "Deactivate MagSafe" func perform() async throws -> some IntentResult { deactivateMeross.post() return .result() } } // // AppShortcut.swift // Runner import Foundation import AppIntents @available(iOS 17, *) struct ActivateMagSafeShortcuts: AppShortcutsProvider { @AppShortcutsBuilder static var appShortcuts: [AppShortcut] { AppShortcut( intent: ActivateMagSafeIntent(), phrases: ["Activate MagSafe"] ) AppShortcut( intent: DeactivateMagSafeIntent(), phrases: ["Deactivate MagSafe"] ) } } With this Code I can add the shortcuts to the shortcuts app. Problem As long as my device is attached to the debugger, everything is working just fine and I am able to control my smart plug with the shortcuts. But after I detached my phone from the debugger, the shortcuts are only working every second run. After every other run, I get an iOS error message like 'Couldn't Communicate with a helper application' or 'App was terminated unexpectedly'. Is there anybody who has been facing the same issue or has any idea why this is happening? Thanks in advance!
Posted
by
Post not yet marked as solved
3 Replies
808 Views
I am trying to create a simple app that "blocks" other apps if a certain condition is not met. I am currently using the IOS shortcuts and have set up an automation that opens my app A whenever another app B opens. If the condition is not met i imagine the flow to look like: Open app A. My app B opens instead. I check a box in my app B. I navigate back to app A and it works as expected. If the condition already is met the app A would work as expected from the beginning. What is have tried so far My first attempt involved using an AppIntent and changing the openAppWhenRun programmatically based on the condition. I did however learn pretty quickly that changing the value of openAppWhenRun does not change if the AppIntent actually opens my app. The code for this looked like this where the value of openAppWhenRun is changed in another function. struct BlockerIntent: AppIntent { static let title: LocalizedStringResource = "Blocker App" static let description: LocalizedStringResource = "Blocks an app until condition is met" static var openAppWhenRun: Bool = false @MainActor func perform() async throws -> some IntentResult { return .result() } } Another attempt involved setting openAppWhenRun to false in an outer AppIntent and opening another inner AppIntent if the condition is met. If the condition in my app is met openAppWhenRun is set to true and instead of opening the inner AppIntent an Error is thrown. This functions as expected but there is an error notification showing every time I open the "blocked" app. struct BlockerIntent: AppIntent { static let title: LocalizedStringResource = "Blocker App" static let description: LocalizedStringResource = "Blocks an app until condition is met" static var openAppWhenRun: Bool = false func perform() async throws -> some IntentResult & OpensIntent { if (BlockerIntent.openAppWhenRun) { throw Error.notFound } return .result(opensIntent: OpenBlockerApp()) } enum Error: Swift.Error, CustomLocalizedStringResourceConvertible { case notFound var localizedStringResource: LocalizedStringResource { switch self { case .notFound: return "Ignore this message" } } } } struct OpenBlockerApp: AppIntent { static let title: LocalizedStringResource = "Open Blocker App" static let description: LocalizedStringResource = "Opens Blocker App" static var openAppWhenRun: Bool = true @MainActor func perform() async throws -> some IntentResult { return .result() } } My third attempt look similar to the previous one but instead I used two different inner AppIntents. The only difference between the two were that on had openAppWhenRun = false and the other had openAppWhenRun = true. struct BlockerIntent: AppIntent { static let title: LocalizedStringResource = "Blocker App" static let description: LocalizedStringResource = "Blacks an app until condition is met" static var openAppWhenRun: Bool = false func perform() async throws -> some IntentResult & OpensIntent { if (BlockerIntent.openAppWhenRun) { return .result(opensIntent: DoNotOpenBlockerApp()) } else { return .result(opensIntent: OpenBlockerApp()) } } } Trying this gives me this error: Function declares an opaque return type 'some IntentResult & OpensIntent', but the return statements in its body do not have matching underlying types I have also tried opening the app with a URL link with little to no success often ending up in an infinity loop, I did try the ForegroundContinuableIntent but it did not function as expected since it relies on the users input. Is there any way to do what I am trying to accomplish? I have seen other apps using a similar concept so I feel like this should be possible. Many thanks!
Posted
by
Post not yet marked as solved
1 Replies
449 Views
I'm developing a CarPlay interface to a messaging application but couldn't find how the root CPTemplate, a grid template with button in my case, could activate SiriKit to let the user choose between several actions like we could see in WhatsApp running on CarPlay: There is CPVoiceControlTemplate that seems to do the job but it is only allowed for navigation app category and not messaging and VoIP. Actually my app could activate Siri to compose a message to a selected contact represented by a CPMessageListItem in a CPListTemplate but I couldn't find how to code a CPGridTemplate that activate Siri...
Posted
by
Post not yet marked as solved
2 Replies
878 Views
I have edited the default widget with Intent, but am being hit with the following errors… it runs perfectly fine if I don’t use an Intent in a static widget Could not find an intent with identifier ConfigurationAppIntent, mangledTypeName: Optional("27trainWidgetsConfigExtension22ConfigurationAppIntentV") associateAppIntent(forUserActivity:) Error converting INIntent to App Intent: AppIntents.PerformIntentError.intentNotFound I think it may be something to do with Info.plist?
Posted
by
Post not yet marked as solved
0 Replies
473 Views
I've created a shortcut using an AppIntent and AppIntentProvider. When I try to run the shortcut in the shortcuts app it works well, but if I assign that same shortcut to the new Action Button it shows that something is working (icon shows up on the island) but the perform function is never called. Am I missing something? should I add extra configurations for the action button? thanks
Posted
by
Post not yet marked as solved
0 Replies
352 Views
I have my app that works perfectly fine with app intents and shortcuts in the Shortcut app. I can find my shortcut when I look for my app in spotlight, the only thing that it are not displayed are the suggested entities, even if the param and suggested entities appear on my Shortcut app. I call to the function updateAppShortcutParameters, and I see this error pop up. Could anyone help me understand what I need to do to make it work? Failed to refresh AppShortcut parameters with error: Error Domain=NSOSStatusErrorDomain Code=-10814 "(null)" UserInfo={_LSLine=159, NSUnderlyingError=0x600005417540 {Error Domain=NSOSStatusErrorDomain Code=-10814 "Unable to find this application extension record in the Launch Services database." UserInfo={_LSFunction=_LSPluginFindWithPlatformInfo, _LSLine=679, NSDebugDescription=Unable to find this application extension record in the Launch Services database., SK=MyDemoAppBinary, IS=false}}, _LSFunction=+[LSBundleRecord bundleRecordWithBundleIdentifier:allowPlaceholder:error:]}
Posted
by
Post not yet marked as solved
0 Replies
303 Views
I have a custom intent with multiple parameters. Two of the parameters are set up to handle disambiguation dialog. The intent definition file for each of these parameters is almost identical except for the parameter names and the wording in the siri dialog. Similarly, the code in the intent handler to resolve these parameters is nearly identical. But when disambiguation is invoked, the Disambiguation Introduction is only spoken by siri for one of the two parameters. What triggers the Disambiguation Introduction to be spoken in one and not the other? Here is the intentHandler code to resolve the first parameter (in which siri will speak the Disambiguation Introduction: - (void)resolvePartsListNameForAddPart:(AddPartIntent *)intent withCompletion:(void (^)(INStringResolutionResult *resolutionResult))completion NS_SWIFT_NAME(resolvePartsListName(for:with:)) API_AVAILABLE(ios(13.0), macos(10.16), watchos(6.0)) { ... NSMutableArray *options; options = [[NSMutableArray alloc] init]; NSString *anOption = [NSString stringWithFormat:@"Use '%@' ", intent.partsListName]; // option 1 [options addObject:anOption]; anOption = [NSString stringWithFormat:@"test1"]; // option 2 [options addObject:anOption]; ... anOption = [NSString stringWithFormat:@"test5"]; // option 6 [options addObject:anOption]; completion([INStringResolutionResult disambiguationWithStringsToDisambiguate:[options copy]]); return; ... } Here is the intentHandler code to resolve the second parameter (in which siri DOES NOT speak the Disambiguation Introduction: - (void)resolveChangeForAddPart:(AddPartIntent *)intent withCompletion:(void (^)(INStringResolutionResult *resolutionResult))completion NS_SWIFT_NAME(resolveChange(for:with:)) API_AVAILABLE(ios(13.0), macos(10.16), watchos(6.0)) { ... NSMutableArray *options; options = [[NSMutableArray alloc] init]; NSString *anOption = [NSString stringWithFormat:WOOD_TYPE_PARM]; // option 1 [options addObject:anOption]; // Option 2 anOption = [NSString stringWithFormat:PART_NAME_PARM]; [options addObject:anOption]; // Option 3 anOption = [NSString stringWithFormat:QUANTITY_PARM]; [options addObject:anOption]; // Option 4 anOption = [NSString stringWithFormat:DIMENSION_PARM]; [options addObject:anOption]; // Option 5 anOption = [NSString stringWithFormat:CANCEL_PARM]; [options addObject:anOption]; completion([INStringResolutionResult disambiguationWithStringsToDisambiguate:[options copy]]); return; } Here is the Intents definition for the working parameter where Siri speaks the Disambiguation Introduction: Here is the Intents definition for the non-working parameter Again, what triggers the Disambiguation Introduction to be spoken in one and not the other? FYI: it does not make any difference whether or not the Disambiguation Introduction has the parameters 'count' and 'change' (i.e. if I make the introduction be Hello World, it still doesn't get spoken).
Posted
by
Post not yet marked as solved
0 Replies
361 Views
When I add AppEnity to my model, I receive this error that is still repeated for each attribute in the model. The models are already marked for Widget Extension in Target Membership. I have already cleaned and restarted, nothing works. Will anyone know what I'm doing wrong? Unable to find matching source file for path "@_swiftmacro_21HabitWidgetsExtension0A05ModelfMm.swift" import SwiftData import AppIntents enum FrecuenciaCumplimiento: String, Codable { case diario case semanal case mensual } @Model final class Habit: AppEntity { @Attribute(.unique) var id: UUID var nombre: String var descripcion: String var icono: String var color: String var esHabitoPositivo: Bool var valorObjetivo: Double var unidadObjetivo: String var frecuenciaCumplimiento: FrecuenciaCumplimiento static var typeDisplayRepresentation: TypeDisplayRepresentation = "Hábito" static var defaultQuery = HabitQuery() var displayRepresentation: DisplayRepresentation { DisplayRepresentation(title: "\(nombre)") } static var allHabits: [Habit] = [ Habit(id: UUID(), nombre: "uno", descripcion: "", icono: "circle", color: "#BF0000", esHabitoPositivo: true, valorObjetivo: 1.0, unidadObjetivo: "", frecuenciaCumplimiento: .mensual), Habit(id: UUID(), nombre: "dos", descripcion: "", icono: "circle", color: "#BF0000", esHabitoPositivo: true, valorObjetivo: 1.0, unidadObjetivo: "", frecuenciaCumplimiento: .mensual) ] /* static func loadAllHabits() async throws { do { let modelContainer = try ModelContainer(for: Habit.self) let descriptor = FetchDescriptor<Habit>() allHabits = try await modelContainer.mainContext.fetch(descriptor) } catch { // Manejo de errores si es necesario print("Error al cargar hábitos: \(error)") throw error } } */ init(id: UUID = UUID(), nombre: String, descripcion: String, icono: String, color: String, esHabitoPositivo: Bool, valorObjetivo: Double, unidadObjetivo: String, frecuenciaCumplimiento: FrecuenciaCumplimiento) { self.id = id self.nombre = nombre self.descripcion = descripcion self.icono = icono self.color = color self.esHabitoPositivo = esHabitoPositivo self.valorObjetivo = valorObjetivo self.unidadObjetivo = unidadObjetivo self.frecuenciaCumplimiento = frecuenciaCumplimiento } @Relationship(deleteRule: .cascade) var habitRecords: [HabitRecord] = [] } struct HabitQuery: EntityQuery { func entities(for identifiers: [Habit.ID]) async throws -> [Habit] { //try await Habit.loadAllHabits() return Habit.allHabits.filter { identifiers.contains($0.id) } } func suggestedEntities() async throws -> [Habit] { //try await Habit.loadAllHabits() return Habit.allHabits// .filter { $0.isAvailable } } func defaultResult() async -> Habit? { try? await suggestedEntities().first } }
Posted
by
Post not yet marked as solved
0 Replies
405 Views
I want to "pause" an Intent ( iOS Shortcut Automation ) how can I achieve it? Basically we have a small task to execute, whenever we setup an automation for one app, lets say LinkedIn, our app runs and asks the user whether they still want to continue with LinkedIn or whether they don't want to. The automation to open our app when LinkedIn is opened is working fine. What we want to achieve is that once a user taps on "Continue to LinkedIn" it should "pause" the automation this time and open LinkedIn instead of opening our app again.
Posted
by
Post not yet marked as solved
1 Replies
496 Views
See the image attached. What are the APIs needed to add an action here that shows up across the system. Not a share extension, but the list of actions that are below that. How did Pinterest add theirs here? And it shows up for almost everything you share. I've been looking around and the only thing that looked like maybe is UIActivity. But when I implemented it doesn't show up across other apps. I was also lookin through app shortcut and app intent documentation but I can't find exactly how Pinterest is providing this action here.
Posted
by
Post not yet marked as solved
0 Replies
395 Views
I've created a barebones Multiplatform app and added an App Intent and App Shortcut. When running on iOS, I can see my app show up in Shortcuts and use the intent or App Shortcut as normal. On macOS, my app does not appear in the Shortcuts app, neither the App Shortcut nor the intent. Is there additional configuration required to enable Shortcuts / App Intents on macOS? This is the only code I've added to a brand-new Xcode Multiplatform project: import AppIntents struct OpenIntent: AppIntent { static let title: LocalizedStringResource = "Open MacShortcut" static let description: LocalizedStringResource = "Opens the app" /// Launch your app when the system triggers this intent. static let openAppWhenRun: Bool = true /// Define the method that the system calls when it triggers this event. @MainActor func perform() async throws -> some IntentResult { /// Return an empty result since we're opening the app return .result() } } struct MacShortcutShortcutsProvider: AppShortcutsProvider { static var appShortcuts: [AppShortcut] { AppShortcut( intent: OpenIntent(), phrases: [ "Open a session of \(.applicationName)" ], shortTitle: "Open", systemImageName: "arrow.up.circle.fill" ) } }
Posted
by
Post not yet marked as solved
2 Replies
760 Views
I have an app that relies heavily on AppIntents and Shortcuts and it seems like the latest iOS update broke those but I can't quite figure out what's the issue. The is that no matter what parameter I pick, when running the shortcut it always uses the defaultResult() Here's an example AppEntity: struct IntentBrokerAppEntity: AppEntity { static var typeDisplayRepresentation = TypeDisplayRepresentation(name: "Intent Broker") @Property(title: "Name") var name: String? @Property(title: "Ip") var ip: String? @Property(title: "Port") var port: String? @Property(title: "Username") var username: String? @Property(title: "Password") var password: String? @Property(title: "Tls") var tls: Bool? struct IntentBrokerAppEntityQuery: EntityQuery { func entities(for identifiers: [IntentBrokerAppEntity.ID]) async throws -> [IntentBrokerAppEntity] { return try await suggestedEntities().filter { identifiers.contains($0.id) } } func suggestedEntities() async throws -> [IntentBrokerAppEntity] { let context = PersistenceController.shared.viewContext let brokerService = BrokerService(context: context) return brokerService.getFavorites().map { IntentBrokerAppEntity(broker: $0) } } func defaultResult() async -> IntentBrokerAppEntity? { try? await suggestedEntities().first } } static var defaultQuery = IntentBrokerAppEntityQuery() var id: String // if your identifier is not a String, conform the entity to EntityIdentifierConvertible. var displayString: String var displayRepresentation: DisplayRepresentation { DisplayRepresentation(title: "\(displayString)") } ... This used to work perfectly fine before 17.2, but now instead of choosing the entity the user picked it always falls back to defaultEntity(). In the console I get this warning Failed to build EntityIdentifier. IntentBrokerAppEntity is not a registered AppEntity identifier But I'm not sure if that's related. Does anyone have any ideas on what's going on here? Input much appreciated!
Posted
by
Post not yet marked as solved
0 Replies
657 Views
I'm writing an application with App Shortcuts support. My task is to write a command that will check whether a certain application is open and runs the command. For example: The user installed a command through my application that responds to the Instagram application The user goes to Instagram My team is starting Question: Is it possible to organize this?
Posted
by
Post not yet marked as solved
0 Replies
465 Views
Hello, I'm working on my first app. It's also my first encounter with App Intents. I have a data structure for events that has an ID (String), a name (String), a Date and an image (Data). The user can create them in the app and they are stored with CoreData. I wanted to have a widget that would allow the user to choose from their list of events and display that event in the widget. The list should appear in the widget configuration and it would be a list of the names and (if possible) the image. I think I have found how to access the information from the widget, but I cannot figure out how to have the list appear in the configuration. I have been following this guide: https://developer.apple.com/documentation/widgetkit/making-a-configurable-widget?utm_source=pocket_saves. But that one shows hardcoded elements in the list and I haven't been able to find how to have the list change in relation to the content of the app. This is what I have made so far in the AppIntent file: import WidgetKit import AppIntents import CoreData struct EventDetail: AppEntity { static var defaultQuery: EventQuery = EventQuery() var id: String var date: Date var image: Data var title: String static var typeDisplayRepresentation: TypeDisplayRepresentation = "Event" var displayRepresentation: DisplayRepresentation { DisplayRepresentation(title: "\(id) \(title)") } } struct EventQuery: EntityQuery{ func entities(for identifiers: [EventDetail.ID]) async throws -> [EventDetail] { return fill_event_details(events_list: getEventDataIntent()) } func suggestedEntities() async throws -> [EventDetail] { fill_event_details(events_list: getEventDataIntent()).filter { $0.id != "-" } } func defaultResult() async -> EventDetail? { try? await suggestedEntities().first } } struct ConfigurationAppIntent: WidgetConfigurationIntent { static var title: LocalizedStringResource = "Select an event" static var description = IntentDescription("This is an example widget.") // An example configurable parameter. @Parameter(title: "Event") var event: EventDetail // init(events: [UserCountdowns]) { // self.event = fill_event_details(events_list: events)[0] // print("AppIntent") // print(self.event.title) // } init() { } } func fill_event_details(events_list: [UserCountdowns]) -> [EventDetail] { var entities_list: [EventDetail]? let events = getEventDataIntent() for event in events { entities_list!.append(EventDetail(id: event.id!, date: event.date!, image: event.image!, title: event.title!)) } return entities_list ?? [EventDetail(id: "-", date: Date(), image: Data(), title: "empty")] } func getEventDataIntent() -> [UserCountdowns] { let context = PersistenceController.shared.container.viewContext let request = UserCountdowns.fetchRequest() var result: [UserCountdowns]! do { result = try context.fetch(request) } catch { print(error) } return result } I have been trying a few things in the widget's code but I haven't been able to make anything work, so I don't really have anything worth sharing, I think. This is the code for the UserCountdowns structure: extension UserCountdowns { @nonobjc public class func fetchRequest() -> NSFetchRequest<UserCountdowns> { return NSFetchRequest<UserCountdowns>(entityName: "UserCountdowns") } @NSManaged public var date: Date? @NSManaged public var image: Data? @NSManaged public var title: String? @NSManaged public var id: String? } Could anyone help me with this, please? What am I missing or what would the next step be? Let me know if there is any other part of the code I should share. Thank you in advance!
Posted
by
Post not yet marked as solved
0 Replies
306 Views
@MainActor perform() async throws -> some IntentResult { // ... switch locationManager.authorizationStatus { case .denied, .restricted: throw UserLocationError.permissionDenied case .notDetermined: await locationManager.requestWhenInUseAuthorization() // to ask permission default: break } // ... } Here is my code. When the authorizationStatus is .notDetermined, it invokes requestWhenInUseAuthorization() method on the main thread, but throws UserLocationError.permissionDenied immediately, eventhough I didn't deny the permission. It's really weird and unexpected that it throws UserLocationError.permissionDenied when the status is not .denied or .restricted Even it invokes requestWhenInUseAuthorization(), there's no alert for asking permission If there's any solution, please let me know
Posted
by
Post not yet marked as solved
1 Replies
341 Views
How to disable iOS Shortcut ( Automation ) Programmatically ? I have made an automation to open my app whenever a user opens Facebook app. When the user taps on "Continue with Facebook" the automation which is forcing to open my App show be disabled for 2 minutes. How can I achieve this?
Posted
by