英文:
On Xcode 11, how can I configure an Intent to run in the background?
问题
TL;DR
在iOS 13和Xcode 11上,我如何配置一个Intent在后台运行并只返回结果,以便将其用作Shortcuts应用程序中其他操作的输入?
Details of what I'm trying to achieve
我的应用程序有一个歌曲列表,我希望通过Shortcuts暴露出来(实际上是有关歌曲的元数据,而不是歌曲本身)。想法是为高级用户提供一种将这个音乐数据库与其他他们想要的应用程序或操作集成的方法。例如,有人可能会发现获取下个月即将发布的音乐列表并将其用于为每首歌曲创建日历事件非常有用。在Shortcuts应用程序中访问此列表可以使他们实现这一目标。
我已经创建了一个名为“List All Unread Music Releases”的Intent,并将其响应定义为包含有关每首歌曲的信息的对象列表。问题是,当我转到Shortcuts应用程序,创建一个使用此Intent的新快捷方式并运行它时,它会打开我的应用程序而不是在后台运行。
Steps I've done to create and configure Intents
以下是我配置项目中意图的步骤的高级定义。下一部分将包含实际源代码和截图。
- 创建一个新的SiriKit意图定义文件。
- 创建一个新的Intent。
- 定义其标题、描述、参数,并禁用“意图适用于Siri建议”复选框。
- 将响应属性定义为数组(因为它将是一组歌曲),并配置输出为此数组属性。
- 创建一个新的Intents扩展,禁用“包括UI扩展”复选框。这里的想法是在后台处理用户请求并返回带有结果的列表 - 不需要UI。
- 在Info.plist文件中的Intents扩展目标中,使用步骤2中创建的意图的名称来定义IntentsSupported数组。
- 使
IntentHandler
类实现为步骤2中创建的意图生成的协议。
Code samples and screenshots
我的SiriKit意图定义文件和GetUnreadReleases意图:
GetUnreadReleases意图响应:
Intents扩展的IntentHandler
类:
import Intents
class IntentHandler: INExtension, GetUnreadReleasesIntentHandling {
func handle(intent: GetUnreadReleasesIntent, completion: @escaping (GetUnreadReleasesIntentResponse) -> Void) {
let response = GetUnreadReleasesIntentResponse(code: .success, userActivity: nil)
let release1 = IntentRelease(identifier: "1", display: "Teste 1")
release1.name = "Name test 1"
release1.artist = "Artist test 1"
response.releases = [release1]
completion(response)
}
func resolveMediaType(for intent: GetUnreadReleasesIntent, with completion: @escaping (IntentMediaTypeResolutionResult) -> Void) {
if intent.mediaType == .unknown {
completion(.needsValue())
} else {
completion(.success(with: intent.mediaType))
}
}
override func handler(for intent: INIntent) -> Any {
// This is the default implementation. If you want different objects to handle different intents,
// you can override this and return the handler you want for that particular intent.
return self
}
}
Intents扩展的Info.plist
文件:
Conclusion
因此,我希望这个意图在后台运行,根据用户定义的参数组装歌曲列表,并返回此列表以供Shortcuts应用程序中的其他操作使用。
似乎以前的Intents编辑器版本(Xcode < 11 / iOS < 13.0)有一个“支持后台执行”的复选框,可以做到这一点,但我在Xcode 11上找不到它了。
英文:
TL;DR
On iOS 13 and Xcode 11, how can I configure an Intent to run in the background and just return the result, so it can be used as the input for other actions in the Shortcuts app?
Details of what I'm trying to achieve
My app has a list of songs that I want to expose via Shortcuts (actually, metadata about the song, not the song itself). The idea is to give advanced users a way to integrate this database of music with other apps or actions they want. For example, one may find useful to get a list of upcoming music for the next month, and use it to create Calendar events for each song. Having access to this list on the Shortcuts app can enable them to do this.
I have created an Intent called "List All Unread Music Releases" and defined its response as a list of objects that contains information about each song. The problem is, when I go to the Shortcuts app, create a new shortcut using this Intent, and run it, it opens my app instead of running in the background.
Steps I've done to create and configure Intents
Here's a high level definition of what I did to configure Intents in the project. The next section will have the actual source code and screenshots.
- Created a new SiriKit Intent Definition File.
- Created a new Intent.
- Defined it's Title, Description, Parameters, and disabled the "Intent is eligible for Siri Suggestions" checkbox.
- Defined the response property as an Array (because it's going to be a list of songs), and configured the Output to be this array property.
- Created a new Intents Extension, with the checkbox "Include UI Extension" disabled. The idea here is to process the user request in the background and return a list with the results - no UI required.
- In the Intents Extension target, defined the IntentsSupported array inside Info.plist with the name of the intent created in step 2.
- Made the
IntentHandler
class implement the protocol generated for the intent created in step 2.
Code samples and screenshots
My SiriKit Intent Definition File and the GetUnreadReleases Intent:
The GetUnreadReleases Intent response:
The Intents Extension IntentHandler
class:
import Intents
class IntentHandler: INExtension, GetUnreadReleasesIntentHandling {
func handle(intent: GetUnreadReleasesIntent, completion: @escaping (GetUnreadReleasesIntentResponse) -> Void) {
let response = GetUnreadReleasesIntentResponse(code: .success, userActivity: nil)
let release1 = IntentRelease(identifier: "1", display: "Teste 1")
release1.name = "Name test 1"
release1.artist = "Artist test 1"
response.releases = [release1]
completion(response)
}
func resolveMediaType(for intent: GetUnreadReleasesIntent, with completion: @escaping (IntentMediaTypeResolutionResult) -> Void) {
if intent.mediaType == .unknown {
completion(.needsValue())
} else {
completion(.success(with: intent.mediaType))
}
}
override func handler(for intent: INIntent) -> Any {
// This is the default implementation. If you want different objects to handle different intents,
// you can override this and return the handler you want for that particular intent.
return self
}
}
The Intents Extension Info.plist
file:
Conclusion
So, I would like this intent to run in the background, assemble the list of songs based on the user defined parameters, and return this list to be used as an input to other actions in the Shortcuts app.
It looks like previous versions of the Intents editor (Xcode < 11 / iOS < 13.0) had a checkbox "Supports background execution" that did just that, but I can't find it anymore on Xcode 11.
答案1
得分: 3
感谢来自苹果开发者论坛的edford,我能够让它正常工作。在意图定义文件中,必须选中“意图适用于Siri建议”复选框,以使后台执行正常工作。
英文:
Thanks to edford from Apple Developer Forums, I was able to make it work. In the intents definition file, the "Intent is eligible for Siri Suggestions" checkbox must be checked for the background execution to work.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论