URL Sessions
the
TimelineProviderAPI is built with completion handlers instead of return values, specifically to make doing asynchronous tasks, like network fetches, easywe can use normal URL sessions end even background session tasks.
since the widget has no app delegate, there’s a new
Viewmodifier, introduced just for widgets, to handle background URL sessions:.onBackgroundURLSessionEvents(matching:_:)
Link
use SwiftUI’s
Linkto make elements of the widget deep link into your app.Linkbehaves likeButton, but instead of passing anaction, we pass adestinationURLwhich will be passed to the app on launch.to read the URL in your views, use the
.onOpenURL(perform:)modifier
Widget bundles
In order to create/support multiple widgets in the same extension, we need to define a
WidgetBundleThe
WidgetBundlewill be the new entry point of the extensionThe
WidgetBundledeclares all available widgets in its body (up to 5 widgets)
@main
struct EmojiRangerBundle: WidgetBundle {
@WidgetBundleBuilder
var body: some Widget {
EmojiRangerWidget()
LeaderboardWidget()
}
}Dynamic configuration
if we don’t know all of the configuration options at build time, we can provide a dynamic list of options via an SiriKit
Intentextension, the same way we would for other Intent-based featuresto create a SiriKit extension, go to
File > New Targetand chooseIntents Extension.in our
Intenteditor we will set our Intent type to something custom (in the screenshot above we set it toHero):

if we look at the definition of our custom type, by default it has two properties:
identifieranddisplayString:

these properties are defined in our Intent extension:
class IntentHandler: INExtension, DynamicCharacterSelectionIntentHandling {
func provideHeroOptionsCollection(for intent: DynamicCharacterSelectionIntent,
with completion: @escaping (INObjectCollection<Hero>?, Error?) -> Void) {
let characters: [Hero] = CharacterDetail.availableCharacters.map { character in
let hero = Hero(identifier: character.name, display: character.name)
return hero
}
let remoteCharacters: [Hero] = CharacterDetail.remoteCharacters.map { character in
let hero = Hero(identifier: character.name, display: character.name)
return hero
}
let collection = INObjectCollection(items: characters + remoteCharacters)
completion(collection, nil)
}
override func handler(for intent: INIntent) -> Any {
return self
}
}lastly, we will need to update our
IntentTimelineProviderto support our dynamic configuration
