En raison de la nature toujours active d’un widget, Apple a introduit un moyen pour les développeurs d’actualiser un widget pour garantir son efficacité énergétique et empêcher les développeurs d’exploiter la puissance de traitement d’un appareil.
Dans cet article, j’aimerais vous montrer ce qu’il faut pour actualiser efficacement vos widgets et discuter des meilleures pratiques à suivre lors de l’actualisation de vos widgets.
Alors sans plus tarder, commençons !
Comme d’habitude, utilisons un exemple de widget que j’ai récemment créé pour montrer comment mettre à jour ou actualiser un widget.
Comme vous pouvez le voir, l’exemple de widget commencera par un compte à rebours de 60 secondes. Une fois le compte à rebours terminé, le widget lancera immédiatement le prochain cycle de compte à rebours.
À l’aide de ce widget de compte à rebours, nous pouvons facilement surveiller la façon dont un widget est mis à jour et ce qui se passera après la fin d’une session d’actualisation.
La première méthode que nous pouvons utiliser pour actualiser un widget est assez simple, mais elle ne fonctionne que pour afficher des dates dynamiques. L’idée est de tirer parti des Text afficher dans SwiftUI et laisser le système gérer l’actualisation pour nous.
Par exemple, si nous voulons afficher un compte à rebours de 60 secondes, nous pouvons écrire ceci :
let components = DateComponents(second: totalCountdown + 1) let futureDate = Calendar.current.date(byAdding: components, to: Date())!
// Show dynamic date in Text view Text(futureDate, style: .timer)
Dans cet esprit, l’affichage d’un compte à rebours dans un widget est assez simple.
struct CountdownWidgetView: View {
var body: some View { Text(getFutureDate(), style: .timer) .monospacedDigit() .padding(4) .font(.headline) .multilineTextAlignment(.center) .background(.red) }
private func getFutureDate() -> Date { let components = DateComponents(second: 60) let futureDate = Calendar.current.date(byAdding: components, to: Date())! return futureDate } }
Regarde ça article par Apple pour en savoir plus sur l’affichage d’informations actualisées basées sur le temps dans votre widget même lorsqu’il n’est pas en cours d’exécution.
Maintenant que nous avons créé le compte à rebours pour notre widget de compte à rebours, concentrons-nous sur les autres éléments de l’interface utilisateur du widget. Nous devrons utiliser le fournisseur de chronologie pour les éléments d’interface utilisateur qui n’affichent pas de dates dynamiques.
Tout d’abord, définissons l’entrée de chronologie que le fournisseur de chronologie utilisera avec ce code :
struct CountdownEntry: TimelineEntry { let date: Date let status: String let gaugeValue: CGFloat }
Les CountdownEntryLes paramètres de sont assez explicites :
date: La date et l’heure d’actualisation du widget
status: L’état actuel du widget
gaugeValue: Le nombre affiché au centre de la jauge
Les paramètres du widget compte à rebours
Nous devons implémenter trois méthodes lors de la création d’un fournisseur de chronologie. Pour cet article, je me concentrerai sur la mise en œuvre de la getTimeline(in:completion:) méthode. Pour les deux autres méthodes, vous pouvez en savoir plus ici.
Le but principal de getTimeline(in:completion:) est de faire savoir au système quand et quoi mettre à jour. Cela peut être fait en alimentant le système avec un objet de chronologie composé d’un tableau d’entrées de chronologie.
Pour notre widget de compte à rebours, un objet de chronologie représentera un compte à rebours de 60 à 0. En d’autres termes, un objet de chronologie sera composé de 61 entrées de chronologie, avec chaque entrée à une seconde d’intervalle. Dans cet esprit, nous pouvons mettre en œuvre le getTimeline(in:completion:) méthode comme ceci:
// Entries required for 1 countdown session (60 seconds) var entries = [CountdownEntry]()
// Generate 61 entries to show countdown from 60 - 0 for i in 0...totalCountdown {
// Determine widget refresh date & create an entry let components = DateComponents(second: i) let refreshDate = Calendar.current.date(byAdding: components, to: Date())!
// Calculate gauge value let gaugeValue = CGFloat(totalCountdown - i)
// Determine status // Status will become "Waiting..." when `gaugeValue` reached zero let status = gaugeValue == 0 ? "Waiting refresh..." : "Counting down..."
// Create a timeline using `entries` let timeline = Timeline(entries: entries, policy: .atEnd) completion(timeline) }
À partir du code ci-dessus, notez comment les entrées de la chronologie sont générées à l’aide d’une boucle for. Une fois que tout est généré, nous pouvons créer un objet de chronologie et déclencher le gestionnaire d’achèvement.
Chaque fois que le gestionnaire d’achèvement est appelé, cela marque le début d’une session d’actualisation. Dans une session d’actualisation, le widget s’actualise en fonction de la date de chaque entrée de chronologie. Une fois la dernière entrée de chronologie traitée, la session d’actualisation se termine.
L’image suivante illustre une session d’actualisation du widget de compte à rebours :
Le cycle de session de rafraîchissement
À ce stade, vous vous demandez peut-être comment nous pouvons indiquer au système quand démarrer la prochaine session d’actualisation. C’est là que la politique de rafraîchissement entre en jeu.
Au moment de la rédaction de cet article, Apple propose trois types de politiques d’actualisation :
atEnd: WidgetKit peut démarrer la prochaine session d’actualisation juste après la fin de la précédente. Il n’y a aucune garantie que la prochaine session commencera immédiatement car le système décidera du meilleur moment pour lancer la prochaine session de rafraîchissement.
after(Date): WidgetKit ne peut démarrer la prochaine session d’actualisation qu’après une date et une heure spécifiques. Juste comme atEndle système décidera du meilleur moment pour démarrer la prochaine session d’actualisation.
never: WidgetKit ne démarrera pas une autre session d’actualisation jusqu’à ce que nous appelions explicitement reloadTimelines(ofKind:) dans l’application d’hébergement. La session de rafraîchissement commencera immédiatement après reloadTimelines(ofKind:) est appelé.
Pour notre widget de compte à rebours, puisque nous utilisons atEndvous pouvez voir que le prochain cycle de compte à rebours commence juste après la fin du précédent.
Pour le forcer à démarrer cinq secondes après la fin du cycle précédent, nous pouvons procéder ainsi :
// Next refresh session start 5s after the last entry let lastUpdate = entries.last!.date let nextUpdate = Calendar.current.date(byAdding: DateComponents(second: 5), to: lastUpdate)!
// Create a timeline using `entries` let timeline = Timeline(entries: entries, policy: .after(nextUpdate))
Voici le widget du compte à rebours mise en œuvre complète (Vous pouvez trouver le code source dans le CountdownWidget dossier).
Lors de l’exécution sur un débogueur, WidgetKit n’impose aucune limitation sur le taux de rafraîchissement du widget. Cela signifie que nous pouvons actualiser le widget aussi souvent que possible. C’est pourquoi nous pouvons actualiser notre widget de compte à rebours toutes les secondes et démarrer le prochain cycle de compte à rebours juste après la fin du cycle précédent. Ceci est particulièrement utile lors du développement et de la mise en œuvre.
D’autre part, comme indiqué dans l’Apple Documentationun widget fréquemment consulté peut avoir un maximum de 40 à 70 actualisations par jour lorsqu’il est exécuté dans un environnement de production, ce qui se traduit approximativement par un widget actualisé toutes les 15 à 60 minutes.
Notez que les intervalles mentionnés ci-dessus varieront très probablement en raison de divers types de facteurs. Par conséquent, nous devons suivre les meilleures pratiques données par Apple lors du remplissage d’une chronologie :
Remplissez une chronologie avec autant de dates futures (entrées de chronologie) que possible.
Gardez l’intervalle des entrées de chronologie dans la chronologie aussi grand que possible.
Assurez-vous que chaque entrée de chronologie dans une chronologie est espacée d’au moins cinq minutes environ.
Comment mettre à jour ou actualiser un widget ? | par Lee Kah Seng
Mise à jour des widgets avec le fournisseur de chronologie
En raison de la nature toujours active d’un widget, Apple a introduit un moyen pour les développeurs d’actualiser un widget pour garantir son efficacité énergétique et empêcher les développeurs d’exploiter la puissance de traitement d’un appareil.
Dans cet article, j’aimerais vous montrer ce qu’il faut pour actualiser efficacement vos widgets et discuter des meilleures pratiques à suivre lors de l’actualisation de vos widgets.
Alors sans plus tarder, commençons !
Comme d’habitude, utilisons un exemple de widget que j’ai récemment créé pour montrer comment mettre à jour ou actualiser un widget.
Découvrez l’exemple de démo du widget ici.
Comme vous pouvez le voir, l’exemple de widget commencera par un compte à rebours de 60 secondes. Une fois le compte à rebours terminé, le widget lancera immédiatement le prochain cycle de compte à rebours.
À l’aide de ce widget de compte à rebours, nous pouvons facilement surveiller la façon dont un widget est mis à jour et ce qui se passera après la fin d’une session d’actualisation.
La première méthode que nous pouvons utiliser pour actualiser un widget est assez simple, mais elle ne fonctionne que pour afficher des dates dynamiques. L’idée est de tirer parti des
Text
afficher dans SwiftUI et laisser le système gérer l’actualisation pour nous.Par exemple, si nous voulons afficher un compte à rebours de 60 secondes, nous pouvons écrire ceci :
let components = DateComponents(second: totalCountdown + 1)
let futureDate = Calendar.current.date(byAdding: components, to: Date())!
// Show dynamic date in Text view
Text(futureDate, style: .timer)
Dans cet esprit, l’affichage d’un compte à rebours dans un widget est assez simple.
struct CountdownWidgetView: View {
var body: some View {
Text(getFutureDate(), style: .timer)
.monospacedDigit()
.padding(4)
.font(.headline)
.multilineTextAlignment(.center)
.background(.red)
}
private func getFutureDate() -> Date {
let components = DateComponents(second: 60)
let futureDate = Calendar.current.date(byAdding: components, to: Date())!
return futureDate
}
}
Cliquez ici pour voir la démo du compte à rebours.
Maintenant que nous avons créé le compte à rebours pour notre widget de compte à rebours, concentrons-nous sur les autres éléments de l’interface utilisateur du widget. Nous devrons utiliser le fournisseur de chronologie pour les éléments d’interface utilisateur qui n’affichent pas de dates dynamiques.
Tout d’abord, définissons l’entrée de chronologie que le fournisseur de chronologie utilisera avec ce code :
struct CountdownEntry: TimelineEntry {
let date: Date
let status: String
let gaugeValue: CGFloat
}
Les
CountdownEntry
Les paramètres de sont assez explicites :date
: La date et l’heure d’actualisation du widgetstatus
: L’état actuel du widgetgaugeValue
: Le nombre affiché au centre de la jaugeNous devons implémenter trois méthodes lors de la création d’un fournisseur de chronologie. Pour cet article, je me concentrerai sur la mise en œuvre de la
getTimeline(in:completion:)
méthode. Pour les deux autres méthodes, vous pouvez en savoir plus ici.Le but principal de
getTimeline(in:completion:)
est de faire savoir au système quand et quoi mettre à jour. Cela peut être fait en alimentant le système avec un objet de chronologie composé d’un tableau d’entrées de chronologie.Pour notre widget de compte à rebours, un objet de chronologie représentera un compte à rebours de 60 à 0. En d’autres termes, un objet de chronologie sera composé de 61 entrées de chronologie, avec chaque entrée à une seconde d’intervalle. Dans cet esprit, nous pouvons mettre en œuvre le
getTimeline(in:completion:)
méthode comme ceci:func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
let totalCountdown = 60
// Entries required for 1 countdown session (60 seconds)
var entries = [CountdownEntry]()
// Generate 61 entries to show countdown from 60 - 0
for i in 0...totalCountdown {
// Determine widget refresh date & create an entry
let components = DateComponents(second: i)
let refreshDate = Calendar.current.date(byAdding: components, to: Date())!
// Calculate gauge value
let gaugeValue = CGFloat(totalCountdown - i)
// Determine status
// Status will become "Waiting..." when `gaugeValue` reached zero
let status = gaugeValue == 0 ? "Waiting refresh..." : "Counting down..."
let entry = CountdownEntry(
date: refreshDate,
status: status,
gaugeValue: gaugeValue
)
entries.append(entry)
}
// Create a timeline using `entries`
let timeline = Timeline(entries: entries, policy: .atEnd)
completion(timeline)
}
À partir du code ci-dessus, notez comment les entrées de la chronologie sont générées à l’aide d’une boucle for. Une fois que tout est généré, nous pouvons créer un objet de chronologie et déclencher le gestionnaire d’achèvement.
Chaque fois que le gestionnaire d’achèvement est appelé, cela marque le début d’une session d’actualisation. Dans une session d’actualisation, le widget s’actualise en fonction de la date de chaque entrée de chronologie. Une fois la dernière entrée de chronologie traitée, la session d’actualisation se termine.
L’image suivante illustre une session d’actualisation du widget de compte à rebours :
À ce stade, vous vous demandez peut-être comment nous pouvons indiquer au système quand démarrer la prochaine session d’actualisation. C’est là que la politique de rafraîchissement entre en jeu.
Au moment de la rédaction de cet article, Apple propose trois types de politiques d’actualisation :
atEnd
:WidgetKit
peut démarrer la prochaine session d’actualisation juste après la fin de la précédente. Il n’y a aucune garantie que la prochaine session commencera immédiatement car le système décidera du meilleur moment pour lancer la prochaine session de rafraîchissement.after(Date)
:WidgetKit
ne peut démarrer la prochaine session d’actualisation qu’après une date et une heure spécifiques. Juste commeatEnd
le système décidera du meilleur moment pour démarrer la prochaine session d’actualisation.never
:WidgetKit
ne démarrera pas une autre session d’actualisation jusqu’à ce que nous appelions explicitementreloadTimelines(ofKind:)
dans l’application d’hébergement. La session de rafraîchissement commencera immédiatement aprèsreloadTimelines(ofKind:)
est appelé.Pour notre widget de compte à rebours, puisque nous utilisons
atEnd
vous pouvez voir que le prochain cycle de compte à rebours commence juste après la fin du précédent.Pour le forcer à démarrer cinq secondes après la fin du cycle précédent, nous pouvons procéder ainsi :
// Next refresh session start 5s after the last entry
let lastUpdate = entries.last!.date
let nextUpdate = Calendar.current.date(byAdding: DateComponents(second: 5),
to: lastUpdate)!
// Create a timeline using `entries`
let timeline = Timeline(entries: entries, policy: .after(nextUpdate))
Voici le widget du compte à rebours mise en œuvre complète (Vous pouvez trouver le code source dans le
CountdownWidget
dossier).Lors de l’exécution sur un débogueur,
WidgetKit
n’impose aucune limitation sur le taux de rafraîchissement du widget. Cela signifie que nous pouvons actualiser le widget aussi souvent que possible. C’est pourquoi nous pouvons actualiser notre widget de compte à rebours toutes les secondes et démarrer le prochain cycle de compte à rebours juste après la fin du cycle précédent. Ceci est particulièrement utile lors du développement et de la mise en œuvre.D’autre part, comme indiqué dans l’Apple Documentationun widget fréquemment consulté peut avoir un maximum de 40 à 70 actualisations par jour lorsqu’il est exécuté dans un environnement de production, ce qui se traduit approximativement par un widget actualisé toutes les 15 à 60 minutes.
Notez que les intervalles mentionnés ci-dessus varieront très probablement en raison de divers types de facteurs. Par conséquent, nous devons suivre les meilleures pratiques données par Apple lors du remplissage d’une chronologie :
Télécharger ici