[SWIFT] Ajout de Widget pour l'application iOS 14 (Widget normal, Widget configurable à l'aide des intentions)

** Cet article décrit les éléments suivants: ** **

  1. Ajouter un widget à une application existante
  2. ⭐️ Ajoutez des widgets qui permettent aux utilisateurs de configurer le contenu (comme la sélection de la ville)

ezgif-6-bf9e4b4783c9.gif

Vous pouvez vérifier le code source complété ici.

Ajout de widgets aux applications existantes

Créer une cible d'application

L'ajout de widgets à votre application iOS existante est facile. Ajoutez la cible Widget Extension.

image

Maintenant, assurez-vous d'avoir coché la case intitulée «Inclure l'intention de configuration». C'est parce que vous aurez besoin de ce fichier de configuration dans la partie 2 de cet article.

image

Structure de données

Vous devriez maintenant voir un nouveau dossier appelé WidgetExample-Widget. Cliquez pour ouvrir le fichier WidgetExample_Widget.swift, supprimez le contenu de ce fichier et suivez ce guide.

Vous pouvez créer la structure de données des données que vous souhaitez afficher dans le widget. Dans cet exemple, nous afficherons les informations sur le chat!

struct CatEntry: TimelineEntry {
    var date: Date
    
    var name: String
    var lastFed: Date
    var lastPlayedWith: Date
}

Structure de ʻCreate IntentTimelineProvider`

La structure ʻIntentTimelineProviderfournit trois types de contenu: 1>placeholders'affiche lorsque le widget est chargé. 2>getSnapshotapparaîtra dans la galerie de widgets. 3>getTimeline` est utilisé pour l'affichage réel du widget.

struct CatProviderStatic: TimelineProvider {
    typealias Entry = CatEntry

    func getSnapshot(in context: Context, completion: @escaping (CatEntry) -> Void) {
        //TODO
    }

    func getTimeline(in context: Context, completion: @escaping (Timeline<CatEntry>) -> Void) {
        //TODO
    }

    func placeholder(in context: Context) -> CatEntry {
        //TODO
    }

}
func getSnapshot(in context: Context, completion: @escaping (CatEntry) -> Void) {
    let entry = CatEntry(date: Date(), name: "", lastFed: Date(), lastPlayedWith: Date())
    completion(entry)
}
func placeholder(in context: Context) -> CatEntry {
    return CatEntry(date: Date(), name: "", lastFed: Date(), lastPlayedWith: Date())
}

Pour la fonction getSnapshot, vous pouvez fournir des exemples de valeurs dans la vue du widget afin que l'utilisateur puisse comprendre ce que fournit votre widget: Pour la vue de l'espace réservé du nom du chat, Vous pouvez afficher des valeurs vides ou des exemples de valeurs comme: nom du chat Et pour l'affichage de la chronologie, vous pouvez fournir le contenu réel à afficher. Cet exemple affiche simplement les valeurs de données statiques. Dans votre application, Core Data (Cliquez ici pour un article sur la façon de partager ces données), ou en ligne, à partir de CloudKit, ou Vous pouvez récupérer le contenu de ʻUserDefaults`.

func getTimeline(in context: Context, completion: @escaping (Timeline<CatEntry>) -> Void) {
    let entry = CatEntry(date: Date(), name: "Nekonohi", lastFed: Date(), lastPlayedWith: Date())
    let timeline = Timeline(entries: [entry], policy: .atEnd)
    completion(timeline)
}

Conception de la vue du widget

Vous pouvez maintenant concevoir la vue SwiftUI du widget.

struct CatWidgetView: View {
    
    @Environment(\.widgetFamily) var family
    
    var entry: CatEntry
    
    var body: some View {
        
        VStack {
            
            if family == .systemMedium || family == .systemLarge {
                Image("kitty")
                    .resizable()
                    .frame(width: 50, height: 50)
                    .padding(.vertical, 5)
            }
            
            Text(entry.name)
                .font(.headline)
                .padding(1)
            
            Text("Dernière fois joué" + entry.lastPlayedWith.getString())
                .font(.caption)
                .padding(.horizontal)
            
            Text("Heure du dernier repas" + entry.lastFed.getString())
                .font(.caption)
                .padding(.horizontal)
            
        }
        
    }
    
}

Vous pouvez utiliser la variable @Environment (\ .widgetFamily) var family pour voir la taille du widget.

Cet exemple montre une image d'un chat lorsque la taille du widget est suffisamment grande pour afficher l'image.

if family == .systemMedium || family == .systemLarge {
    Image("kitty")
        .resizable()
        .frame(width: 50, height: 50)
        .padding(.vertical, 5)
}

Codage d'une application de widget

Vous pouvez maintenant coder votre application de widget.

@main
struct CatWidget: Widget {
    
    var body: some WidgetConfiguration {
        IntentConfiguration(kind: "CatWidget", intent: ConfigurationIntent.self, provider: CatProvider()) { entry in
            CatWidgetView(entry: entry)
        }.configurationDisplayName("Chat")
        .description("Voyez quand vous avez nourri et joué avec votre chat.")
    }
    
}

Vous pouvez maintenant exécuter l'application dans le simulateur et ajouter le widget que vous venez de concevoir à votre écran.

image

Permet aux utilisateurs de configurer des widgets

Si vous avez utilisé le widget météo, vous savez que les utilisateurs peuvent sélectionner les villes à afficher en appuyant longuement et en configurant le widget. Vous pouvez ajouter cette fonctionnalité en utilisant le framework ʻIntents` et Target.

ʻIntents` Ajouter une cible de programme

image

Aucun élément d'interface utilisateur n'est nécessaire à ce stade, vous pouvez donc décocher l'option «Inclure l'extension d'interface utilisateur».

image

Sur la page cible d'intentions créée, recherchez la section intitulée «Intentions prises en charge». Créez un nouvel élément nommé ConfigurationIntent. Le nom est «[nom de l'intention] Intention». Le nom de l'intention est affiché dans le fichier .intentdefinition sur la gauche.

スクリーンショット 0002-10-09 15.16.55.png

スクリーンショット 0002-10-09 15.11.01.png

Structure de .intentdefinition

Ensuite, pour le fichier WidgetExample_Widget.intentdefinition dans le widget créé précédemment, ajoutez l'extension ʻIntents` nouvellement créée comme cible d'intention.

<img width="300 alt="image" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635330/a9450674-1f3b-9d1d-f8c0-69221b74e7c2.png ">

Cliquez sur «Configuration» sur le côté gauche de l'écran.

image

Sur le côté droit, assurez-vous qu'il a la même configuration que l'image ci-dessous.

image

Ajoutez ensuite un nouveau paramètre nommé cat.

image

Dans l'écran de réglage des paramètres cat nouvellement créé, sélectionnez String pour le type Type pour utiliser l'identifiant de chat comme entrée.

image

Configuration de ʻIntentHandler`

Ouvrez ensuite le fichier ʻIntentHandler.swift`. Ce fichier donne à l'utilisateur la possibilité de configurer le widget. Dans cet exemple, l'option est l'identifiant du chat.

Si vous ajoutez le mot-clé ConfigurationIntentHandling à côté du type ʻINExtension` de la classe, le logiciel Xcode affichera automatiquement le nom de la fonction suivante à ajouter.

class IntentHandler: INExtension, ConfigurationIntentHandling {
    ...
}

Dans cet exemple, le fichier ʻIntentHandler.swift` terminé ressemble à ceci:

class IntentHandler: INExtension, ConfigurationIntentHandling {
    
    
    func provideCatOptionsCollection(for intent: ConfigurationIntent, searchTerm: String?, with completion: @escaping (INObjectCollection<NSString>?, Error?) -> Void) {
        let catIdentifiers: [NSString] = [
            "Nekonohi",
            "Blé",
            "Azuki"
        ]
        let allCatIdentifiers = INObjectCollection(items: catIdentifiers)
        completion(allCatIdentifiers, nil)
    }
    
    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
    }
    
}

La fonction provideCatOptionsCollection vous oblige à entrer une liste de valeurs. Ces valeurs peuvent en fait être extraites de «Paramètres par défaut de l'utilisateur», «Données de base» ou en ligne. Les valeurs sont codées en dur dans cet exemple.

Utiliser "Core Data" avec "App Extensions"

ʻCreate IntentTimelineProvider`

Dans la partie 1 de cet article, nous avons utilisé TimelineProvider. Cette fois, nous utiliserons ʻIntentTimelineProvider`.

«La structure de données entre IntentTimelineProvider» et «TimelineProvider» est à peu près la même. La différence est que vous devez déclarer un "typealias" supplémentaire.

typealias Intent = ConfigurationIntent

Une autre différence est: Chaque fonction obtient un paramètre supplémentaire ConfigurationIntent qui représente la sélection des intentions.

struct CatProvider: IntentTimelineProvider {
    
    typealias Intent = ConfigurationIntent
    typealias Entry = CatEntry
    
    func placeholder(in context: Context) -> CatEntry {
        let entry = CatEntry(date: Date(), name: "", lastFed: Date(), lastPlayedWith: Date())
        return entry
    }
    
    func getSnapshot(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (CatEntry) -> Void) {
        let entry = CatEntry(date: Date(), name: "Nom du chat", lastFed: Date(), lastPlayedWith: Date())
        completion(entry)
    }
    
    func getTimeline(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (Timeline<CatEntry>) -> Void) {
        let entry = CatEntry(date: Date(), name: configuration.cat ?? "", lastFed: Date(), lastPlayedWith: Date())
        let timeline = Timeline(entries: [entry], policy: .atEnd)
        completion(timeline)
    }
    
}

Vous pouvez utiliser la propriété configuration.cat pour lire la valeur de l'option sélectionnée par l'utilisateur.

let entry = CatEntry(date: Date(), name: configuration.cat ?? "", lastFed: Date(), lastPlayedWith: Date())

Mettez à jour le code de «CatWidget».

Nous avons utilisé StaticConfiguration dans la partie 1, mais cette partie utilise ʻIntentConfiguration (le nom que vous avez défini dans Intentions prises en charge`).

@main
struct CatWidget: Widget {
    
    var body: some WidgetConfiguration {
        IntentConfiguration(kind: "CatWidget", intent: ConfigurationIntent.self, provider: CatProvider()) { entry in
            CatWidgetView(entry: entry)
        }.configurationDisplayName("Chat")
        .description("Voyez quand vous avez nourri et joué avec votre chat.")
    }
    
}

Vous pouvez maintenant exécuter le programme dans le simulateur. Appuyez et maintenez le widget pour voir l'option ʻEdge Widget`, où vous pouvez renommer le chat.

ezgif-6-bf9e4b4783c9.gif

⭐️

Utiliser "Core Data" avec "App Extensions"

Visitez cette page Web pour une liste de mes articles Qiita publiés par catégorie.

Recommended Posts

Ajout de Widget pour l'application iOS 14 (Widget normal, Widget configurable à l'aide des intentions)
Remarques sur l'utilisation de BLE dans les applications iOS
Ajout de la prise en charge du trackpad (UIPointerInteraction) pour les applications iPad iOS