Créer un blog dans Swift avec Oracle Content Management headless

Introduction

Un environnement de développement iOS utilisant Swift et SwiftUI peut être un outil puissant pour créer des applications qui utilisent du contenu d'Oracle Content Management. Grâce au bon modèle de contenu, vous pouvez rapidement créer l'interface utilisateur qui constitue une application de blog typique.

Dans ce tutoriel, nous allons créer une application de blog iOS simple dans Swift en utilisant Oracle Content Management comme CMS headless ainsi que son kit de développement logiciel (SDK) pour la diffusion de contenu. Cet exemple iOS est disponible sur GitHub.

Ce tutoriel comporte trois étapes :

  1. Préparer Oracle Content Management
  2. Créer l'application Blog dans Xcode
  3. Exécutez l'application

Prérequis

Avant de passer à ce tutoriel, nous vous recommandons de lire d'abord les informations suivantes :

Pour suivre ce tutoriel, vous aurez besoin des éléments suivants :

Ce que nous construisons

Notre application de blog se compose de trois pages distinctes qui permettent aux visiteurs d'explorer des articles de blog organisés en sujets.

Cette image animée montre la navigation dans un exemple d'application de blog, en commençant par des sujets, en accédant à une liste d'articles et en affichant enfin un article de blog en détail.

La première page, la page d'accueil, se compose de marques (nom et logo de l'entreprise), de liens et d'une liste de sujets de blog.

La deuxième page, la page de liste d'articles, affiche les aperçus de chaque article de blog appartenant au sujet.

Enfin, la page d'articles affiche l'article de blog final, y compris des informations sur l'auteur du blog.

Pour continuer, vous devez disposer d'un abonnement actif à Oracle Content Management et être connecté avec le rôle Administrateur de contenu.

Etape 1 : Préparer Oracle Content Management

Si vous ne disposez pas encore d'une instance Oracle Content Management, reportez-vous au démarrage rapide pour savoir comment vous inscrire à Oracle Cloud, provisionner une instance Oracle Content Management et configurer Oracle Content Management en tant que CMS headless.

Pour ce tutoriel, vous devez créer un modèle de contenu de l'une des deux manières suivantes. Un pack de ressources téléchargeable est disponible pour remplir votre référentiel vide avec les types de contenu et le contenu associé, ou vous pouvez créer votre propre modèle de contenu et votre propre contenu.

Pour préparer Oracle Content Management :

  1. Créez un canal et un référentiel de ressources.
  2. Créez un modèle de contenu à l'aide de l'une des deux méthodes suivantes :

Création d'un canal et d'un référentiel de ressources

Vous devez d'abord créer un canal et un référentiel de ressources dans Oracle Content Management afin de pouvoir publier du contenu.

Pour créer un canal et un référentiel de ressources dans Oracle Content Management, procédez comme suit :

  1. Connectez-vous à l'interface Web d'Oracle Content Management en tant qu'administrateur.

  2. Choisissez Contenu dans le menu de navigation de gauche, puis choisissez Publier des canaux dans la liste de sélection de l'en-tête de page.

    Cette image présente l'option Canaux de publication sélectionnée dans le menu déroulant de l'en-tête de page Contenu.

  3. Dans l'angle supérieur droit, cliquez sur Créer pour créer un canal. Nommez le canal 'OCEGettingStartedChannel' dans le cadre de ce tutoriel et tenez l'accès public. Cliquez sur Save pour créer le canal.

    Cette image présente le panneau de définition du canal de publication, avec 'OCEGettingStartedChannel' dans le champ Nom du canal.

  4. Choisissez Contenu dans le menu de navigation de gauche, puis choisissez Référentiels dans la liste de sélection de l'en-tête de page.

    Cette image présente l'option Référentiels sélectionnée dans le menu déroulant de l'en-tête de page Contenu.

  5. Dans l'angle supérieur droit, cliquez sur Créer pour créer un référentiel de ressources. Nommez le référentiel de ressources 'OCEGettingStartedRepository' dans le cadre de ce tutoriel.

    Cette image présente le panneau de définition du référentiel, avec 'OCEGettingStartedRepository' dans le champ Nom du référentiel.

  6. Dans le champ Canaux de publication, sélectionnez le canal OCEGettingStartedChannel pour indiquer à Oracle Content Management que le contenu du référentiel OCEGettingStartedRepository peut être publié sur le canal OCEGettingStartedChannel. Lorsque vous avez terminé, cliquez sur Enregistrer.

    Cette image présente le panneau de définition du référentiel, avec 'OCEGettingStartedChannel' dans le champ Canaux de publication.

Créer un modèle de contenu

L'étape suivante consiste à créer un modèle de contenu. Utilisez l'une des deux méthodes suivantes :

Importer le pack de ressources d'échantillons Oracle Content Management

Vous pouvez télécharger un exemple de pack de ressources Oracle Content Management préconfiguré contenant tous les types de contenu et ressources requis pour ce tutoriel. Si vous préférez, vous pouvez également créer votre propre modèle de contenu au lieu de télécharger l'exemple de pack de ressources.

Vous pouvez télécharger une copie du contenu que nous utilisons dans ce tutoriel à partir du pack de ressources d'échantillons Oracle Content Management. Vous pourrez ainsi essayer les types de contenu et modifier leur contenu. Si vous souhaitez importer le pack d'équipements d'échantillons Oracle Content Management, téléchargez l'archive du pack d'équipements OCESamplesAssetPack.zip et extrayez-la dans le répertoire de votre choix :

  1. Téléchargez le pack de ressources Oracle Content Management Samples (OCESamplesAssetPack.zip) à partir de la page Téléchargements d'Oracle Content Management. Extrayez le fichier ZIP téléchargé vers un emplacement sur votre ordinateur. Après l'extraction, cet emplacement inclut un fichier nommé OCEGettingStarted_data.zip.

  2. Connectez-vous à l'interface Web d'Oracle Content Management en tant qu'administrateur.

  3. Choisissez Contenu dans le menu de navigation de gauche, puis choisissez Référentiels dans la liste de sélection de l'en-tête de page. Sélectionnez à présent OCEGettingStartedRepository et cliquez sur le bouton Importer le contenu dans la barre d'actions supérieure.

    Cette image présente la page Référentiels, avec l'élément OCEGettingStartedRepository sélectionné.

  4. Téléchargez OCEGettingStarted_data.zip à partir de votre ordinateur local vers le dossier Documents.

    Cette image montre l'écran de confirmation de téléchargement du fichier OCEGettingStarted_data.zip.

  5. Une fois téléchargé, sélectionnez OCEGettingStarted_data.zip et cliquez sur OK pour importer le contenu dans votre référentiel de ressources.

    Cette image présente le fichier OCEGettingStarted_data.zip sélectionné avec le bouton OK activé.

  6. Une fois le contenu importé, accédez à la page Ressources et ouvrez le référentiel OCEGettingStartedRepository. Vous verrez que toutes les images et tous les éléments de contenu associés ont été ajoutés au référentiel de ressources.

    Cette image montre le référentiel OCEGettingStartedRepository, avec toutes les ressources qui viennent d'être importées.

  7. Cliquez sur Tout sélectionner en haut à gauche, puis sur Publier pour ajouter toutes les ressources importées au canal de publication que vous avez créé précédemment, OCEGettingStartedChannel.

    Cette image présente le référentiel OCEGettingStartedRepository, avec toutes les ressources sélectionnées et l'option Publier dans la barre d'actions visible.

  8. Avant la publication, vous devez valider toutes les ressources. Ajoutez d'abord OCEGettingStartedChannel en tant que canal sélectionné, puis cliquez sur le bouton Valider.

    Cette image présente la page Résultats de la validation, avec le canal OCEGettingStartedChannel ajouté dans le champ Canaux, toutes les ressources à valider et le bouton Valider activé.

  9. Une fois les ressources validées, vous pouvez publier toutes les ressources sur le canal sélectionné en cliquant sur le bouton Publier dans l'angle supérieur droit.

    Cette image présente la page Résultats de la validation, avec le canal OCEGettingStartedChannel ajouté dans le champ Canaux, toutes les ressources validées et le bouton Publier activé.

Une fois cette opération terminée, vous pouvez voir sur la page Ressources que toutes les ressources ont été publiées. (Vous pouvez indiquer l'icône située au-dessus du nom de la ressource.)

Cette image présente la page Equipements, avec toutes les immobilisations publiées.

Après avoir importé le pack d'équipements d'échantillons Oracle Content Management, vous pouvez commencer à créer le blog dans Xcode.

Créer votre propre modèle de contenu

Au lieu d'importer le pack de ressources d'échantillons Oracle Content Management, vous pouvez également créer votre propre modèle de contenu.

Pour ce tutoriel, nous utilisons un type de contenu appelé 'OCEGettingStartedHomePage' pour créer la page d'accueil de notre blog. Cette page d'accueil se compose d'une marque (nom et logo de l'entreprise), d'URL de liens et d'une liste de sujets de blog à inclure sur la page.

Cette image montre la page d'accueil du site de démonstration Cafe Supremo.

Pour créer des types de contenu pour le modèle de contenu :

  1. Connectez-vous à l'interface Web d'Oracle Content Management en tant qu'administrateur.
  2. Choisissez Contenu dans le menu de navigation de gauche, puis choisissez Types d'actif dans la liste de sélection de l'en-tête de page.
  3. Cliquez sur Créer dans l'angle supérieur droit.
  4. Choisissez de créer un type de contenu (et non un type de ressource numérique). Répétez cette opération pour tous les types de contenu requis.

Cette image présente la boîte de dialogue Créer un type de ressource dans l'interface Web d'Oracle Content Management.

Nous allons créer quatre types de contenu, chacun avec son propre ensemble de champs :

Le premier type de contenu, OCEGettingStartedHomePage, doit comporter les champs suivants :

Nom d'affichage Type de champ Requis Nom de l'ordinateur
Nom de la société Champ de texte à valeur unique X company_name
Logo de la société Champ de texte à valeur unique X company_logo
Rubriques Champ de référence à valeurs multiples X rubriques
URL du contact Champ de texte à valeur unique X contact_url
A propos de l'URL Champ de texte à valeur unique X about_url

Voici à quoi doit ressembler votre définition de type de contenu OCEGettingStartedHomePage :

Cette image présente la définition du type de contenu 'OCEGettingStartedHomePage'. Il inclut les champs de données suivants : Nom de la société, Logo de la société, Rubriques, URL de l'interlocuteur et A propos de l'URL.

Le deuxième type de contenu, OCEGettingStartedTopic, doit comporter le champ suivant :

Nom d'affichage Type de champ Requis Nom de l'ordinateur
Miniature Champ d'image à valeur unique X miniature

Voici à quoi doit ressembler votre type de contenu OCEGettingStartedTopic :

Cette image présente la définition du type de contenu 'OCEGettingStartedTopic'. Il inclut ce champ de données : Miniature.

Le troisième type de contenu, OCEGettingStartedAuthor, doit comporter les champs suivants :

Nom d'affichage Type de champ Requis Nom de l'ordinateur
Avatar Champ d'image à valeur unique X avatar

Voici à quoi doit ressembler votre type de contenu OCEGettingStartedAuthor :

Cette image présente la définition du type de contenu 'OCEGettingStartedAuthor'. Il inclut ce champ de données : Avatar.

Le quatrième et dernier type de contenu, OCEGettingStartedArticle, doit comporter les champs suivants :

Nom d'affichage Type de champ Requis Nom de l'ordinateur
Date de publication Champ de date à valeur unique X published_name
Auteur Champ de référence à valeur unique X auteur
Image Champ d'image à valeur unique X image
Légende d'image Champ de texte à valeur unique X image_caption
Contenu de l'article Champ de grand texte à valeur unique X article_content
Sujet Champ de référence à valeur unique X rubrique

Voici à quoi doit ressembler votre type de contenu OCEGettingStartedArticle :

Cette image présente la définition du type de contenu 'OCEGettingStartedArticlePage'. Il inclut les champs de données suivants : Date de publication, Auteur, Image, Légende de l'image, Contenu de l'article et Sujet.

Une fois les types de contenu créés, vous pouvez ajouter ces types de contenu au référentiel que vous avez créé précédemment, OCEGettingStartedRepository :

  1. Connectez-vous à l'interface Web d'Oracle Content Management en tant qu'administrateur.
  2. Accédez à OCEGettingStartedRepository.
  3. Modifiez le référentiel et, sous Types de ressource, indiquez les quatre nouveaux types de contenu. Cliquez sur le bouton Save (Enregistrer) pour enregistrer vos modifications.

Cette image présente la page Modifier le référentiel dans Oracle Content Management, avec les quatre nouveaux types de contenu associés au référentiel OCEGettingStartedRepository.

Après avoir ajouté les types de contenu au référentiel, vous pouvez ouvrir le référentiel OCEGettingStartedRepository sur la page Ressources et commencer à créer vos éléments de contenu pour tous les types de contenu.

Cette image présente les éléments de contenu sur la page Ressources de l'interface Web d'Oracle Content Management, avec des options à gauche pour les collections, les canaux, les langues, les types, la sélection d'élément de contenu et le statut.

Etape 2 : Construire l'application de blog dans Xcode

Pour utiliser notre contenu Oracle Content Management dans une application iOS, nous pouvons utiliser l'exemple de blog iOS, qui est disponible en tant que référentiel open source sur GitHub.

Remarque : n'oubliez pas que l'utilisation de l'exemple iOS est facultative et que nous l'utilisons dans ce tutoriel pour vous lancer rapidement. Vous pouvez également créer votre propre application iOS.

Pour construire le blog dans Swift :

  1. Cloner l'exemple de référentiel
  2. Configurer l'application iOS
  3. Utiliser le kit SDK de contenu pour extraire le contenu

Copier l'exemple de référentiel

L'exemple de blog iOS est disponible en tant que référentiel open source sur GitHub.

Vous devez d'abord cloner l'échantillon de GitHub vers votre ordinateur local :

git clone https://github.com/oracle-samples/oce-ios-blog-sample.git

Une fois l'échantillon cloné, ouvrez le fichier de projet Xcode, BlogDemo.xcodeproj.

Lorsque vous ouvrez l'exemple de projet dans Xcode, il extrait automatiquement la dépendance pour content-management-swift, le package Swift qui implémente le kit SDK Oracle Content Delivery.

Il n'existe aucune autre dépendance tierce pour cette application, donc aucune autre installation manuelle n'est requise. Toutefois, avant d'exécuter l'application, une configuration supplémentaire est requise.

Configurer l'application iOS

Dans cet exemple de blog iOS, vous devez configurer quelques informations afin que le kit SDK Oracle Content Management Content puisse cibler l'URL d'instance correcte avec le jeton de canal correct. Ces valeurs sont utilisées chaque fois que votre application demande des données à partir de votre instance Oracle Content Management.

Ouvrez le fichier credentials.json et modifiez les deux paires clé-valeur pour refléter l'URL d'instance et le jeton de canal associés au canal de publication. Le canal de ce tutoriel est OCEGettingStartedChannel.

{
    "url": "https://samples.mycontentdemo.com",
    "channelToken": "47c9fb78774d4485bc7090bf7b955632"
}

Utiliser le kit SDK de contenu pour extraire le contenu

Oracle Content Management propose un package Swift (content-management-swift) composé des bibliothèques OracleContentCore et OracleContentDelivery pour faciliter la découverte et l'utilisation de contenu dans vos applications. Le package est hébergé sur GitHub.

En savoir plus sur Content SDK pour Swift dans la bibliothèque de documentation Oracle Content Management :

Vous pouvez utiliser ces bibliothèques Content SDK pour extraire du contenu afin de le rendre dans notre application iOS.

Intégration de l'application

Pour demander des données, vous devez fournir certaines informations requises à votre bibliothèque, appelée intégration de l'application. Vous affectez des informations particulières afin que les demandes soient correctement formées et pointent vers l'URL d'instance correcte.

Dans cette démonstration, lors du premier démarrage de l'application, Onboarding.urlProvider est affecté en tant qu'instance de votre propre classe, MyURLProvider. Cela établit l'URL d'instance et le jeton de canal utilisés par la bibliothèque de contenu pour chaque demande effectuée.

Bien que la spécification d'un fournisseur d'URL ne soit pas strictement nécessaire (car les informations d'URL et de jeton peuvent être spécifiées par demande), leur affectation réduit la quantité de code requise pour chaque site d'appel.

@main
struct BlogDemo: App {
    init() {
        // ... 

        // The sample code expects the URL and channel token to be provided by ``OracleContentCore.Onboarding``
        // Assign your ``OracleContentCore.URLProvider`` implementation to the ``OracleContentCore.Onboarding.urlProvider`` property
        Onboarding.urlProvider = MyURLProvider()
        
        // ...
        
    }
}

L'implémentation MyURLProvider lit les données à partir de credentials.json pour obtenir l'URL et le jeton de canal.

{
    "url": "https://samples.mycontentdemo.com",
    "channelToken": "47c9fb78774d4485bc7090bf7b955632"
}

Chaque fois que la bibliothèque de contenu Oracle a besoin de créer une demande, elle extrait la propriété suivante :

/// This function provides the URL to be used for each OracleContentCore request
///
/// Services which implement ``OracleContentCore.ImplementsOverrides`` may provide a different URL and
/// authorization headers (if required) on a call-by-call basis
public var url: () -> URL? = {
  return URL(string: MyURLProvider.credentials.url)
}

Chaque fois que la bibliothèque a besoin de créer une demande, elle récupère également le jeton de distribution :

/// This function provides the delivery channel token to be used for each OracleContentCore request
///
/// Services which implement ``OracleContentCore.ImplementsChannelToken`` may override this value
/// on a call-by-call basis
public var deliveryChannelToken: () -> String? = {
  
  return MyURLProvider.credentials.channelToken
}

En outre, l'affectation à Onboarding.logger permet de définir votre propre implémentation de journalisation. Pour cette démonstration, l'implémentation MyLogger consiste simplement à "imprimer" vers la console. Dans les environnements de production, votre journaliseur peut utiliser la journalisation universelle, les données de base ou toute technologie de votre choix.

@main
struct BlogDemo: App {
    init() {
        // ... 

         Onboarding.logger = MyLogger()
        
        // ...
        
    }
}

Demander des données à l'aide de la bibliothèque Oracle Content

Remarque : tous les codes de demande réseau pour cette démonstration sont disponibles dans BlogNetworking.swift.

Nous pouvons désormais utiliser Content SDK pour extraire du contenu afin de pouvoir le rendre dans l'application iOS.

Le fichier BlogNetworking.swift contient tout le code permettant d'obtenir des données pour l'application. L'objet modèle associé à chaque page appelle diverses méthodes afin d'extraire les données Oracle Content Management.

Données de la page d'accueil

La page d'accueil de notre application est BlogDemoMain.swift, un fichier SwiftUI avec un objet modèle associé. L'objet modèle est responsable de la maintenance de l'état de la page et de l'émission des appels de fonction nécessaires au démarrage du processus d'extraction des données. Lorsque les données sont reçues, l'état de la page change et SwiftUI actualise l'interface utilisateur en conséquence.

Initialement, la page principale demande deux données différentes :

  1. Tout d'abord, nous recherchons l'élément de contenu représentant la page d'accueil du blog.
  2. Ensuite, nous téléchargeons le logo référencé par l'élément de contenu.

Ouvrez BlogNetworking.swift et recherchez la fonction fetchHomePage(), qui effectue la demande initiale.

/// Retrieve the content item which represents the home page of the blog
/// - returns: Asset
public func fetchHomePage() async throws -> Asset {
    let typeNode = QueryNode.equal(field: "type", value: "OCEGettingStartedHomePage")
    let nameNode = QueryNode.equal(field: "name", value: "HomePage")
    let q = QueryBuilder(node: typeNode).and(nameNode)
    
    let result = try await DeliveryAPI
        .listAssets()
        .query(q)
        .fields(.all)
        .limit(1)
        .fetchNextAsync()
        .items
        .first
       
    guard let foundResult = result else {
        throw BlogNetworkingError.homePageNotFound
    }
    
    return foundResult
}

Cette fonction utilise la simultanéité Swift pour demander des données. Tous les objets (ou services) de demande sont espacés de noms de DeliveryAPI. Dans cet exemple, notre objet de demande est listAssets().

Les objets de demande suivants sont une série de composants de constructeur qui nous permettent d'affiner notre demande. Nous avons indiqué des détails de requête, demandé à extraire tous les champs et limité nos données de réponse à un seul objet.

Notre demande à Oracle Content Management est soumise à l'aide du verbe d'appel fetchNextAsync().

Remarque : puisque notre objet de demande commence par "list", le verbe d'appel commence par "fetchNext".

Les demandes "List" renvoient des données indiquant le nombre d'enregistrements renvoyés, si des données supplémentaires existent et un ensemble de résultats (dans la propriété "items").

Notre fonction récupère la première valeur de la propriété "items" et la renvoie. Il s'agit de l'actif représentant notre blog et il contient l'ID du logo, le nom de la société, les URL d'expéditeur et de contact et une liste de sujets.

Avec l'identifiant de logo disponible, nous pouvons émettre notre deuxième demande pour télécharger le logo :

/// Download the logo for display on the home page
/// - parameter logoId: The identifier of the logo to download
/// - returns: BlogImageState 
public func fetchLogo(logoId: String?) async throws -> BlogImageState {
    
    do {
        guard let logoID = logoId else { 
          throw BlogNetworkingError.missingLogoId 
        }
        
        let result = try await DeliveryAPI
            .downloadNative(identifier: logoID)
            .downloadAsync(progress: nil)
        
        guard let image = UIImage(contentsOfFile: result.result.path) else {
            throw OracleContentError.couldNotCreateImageFromURL(URL(string: result.result.path))
        }
        
        return .image(image)
        
    } catch {
        return .error(error)
    }

}

Notre demande et notre appel sont beaucoup plus simples dans cette fonction. Nous créons l'objet de demande à l'aide de downloadNative(identifier: logoID) et nous le soumettons à l'aide du verbe d'appel downloadAsync.

Une fois l'objet téléchargé, nous convertissons les données en UIImage et les renvoyons en tant qu'énumération BlogImageState avec l'image elle-même en tant que valeur associée.

Remarque : cet exemple utilise l'énumération BlogImageState car elle permet de représenter les différents états d'image sans avoir à utiliser des valeurs facultatives. Cela rend l'adoption de SwiftUI très facile.

Données du sujet

Lorsque notre modèle a demandé les données de la page d'accueil, il a exécuté un appel ressemblant à ce qui suit :

self.home = try await self.networking.fetchHomePage()   

Avec la page d'accueil récupérée avec succès, nous devons trouver la collection de valeurs d'actifs qui représentent les sujets de notre blog. Pour ce faire, nous demandons le champ nommé "sujets" dont le type est un ensemble de ressources.

self.topics = try self.home.customField("topics") as [Asset]

BlogDemoMain.swift effectue une itération sur cet ensemble de sujets et représente chacun comme un élément dans une vue de grille. Cette représentation d'interface utilisateur est définie dans Topic.swift et l'objet de modèle associé, TopicModel.swift.

Pour afficher des informations sur un sujet individuel, nous devons effectuer deux tâches :

  1. Nous devons extraire les informations détaillées de chaque sujet.
  2. Nous devons télécharger l'image référencée par chaque sujet.

Dans TopicModel.swift, nous appelons le code réseau pour obtenir la ressource complète :

let fullAsset = try await self.networking.readAsset(assetId: self.topic.identifier)

L'obtention d'informations détaillées sur le sujet est un processus simple. Créez une demande de lecture à l'aide de l'identificateur indiqué, puis extrayez les données.

/// Obtain detailed information about an Asset
/// - parameter assetId: The identifier of the asset to read
/// - returns: Asset
public func readAsset(assetId: String) async throws -> Asset {
    let result = try await DeliveryAPI
        .readAsset(assetId: assetId)
        .fetchAsync()
    
    return result
}

Remarque : toutes les demandes de lecture renvoient un seul objet et sont soumises à l'aide d'un verbe d'appel commençant par "fetch".

Une fois que nous avons extrait les informations détaillées sur notre sujet, nous devons extraire les données qui définissent la miniature, puis les télécharger.

Dans TopicModel.swift, nous obtenons les informations de miniature en demandant le champ personnalisé nommé "thumbnail". Etant donné que les champs personnalisés peuvent être de nombreux types différents, nous devons indiquer explicitement que ce champ est un type de ressource. Une fois la ressource trouvée, nous pouvons obtenir son identifiant.

imageIdentifier = (try fullAsset.customField("thumbnail") as Asset).identifier

Avec l'identificateur disponible, TopicModel.swift peut maintenant demander au code réseau d'extraire le rendu moyen de l'image miniature.

let imageState = await self.networking.downloadMediumRendition(identifier: imageIdentifier)
return imageState

Le code réseau permettant d'obtenir l'image crée un objet de demande "downloadRendition" pour extraire un rendu nommé "Medium" au format jpg. Le verbe d'appel utilisé pour soumettre la demande est "downloadAsync".

Une fois l'objet téléchargé, nous convertissons les données en UIImage et les renvoyons en tant qu'énumération BlogImageState avec l'image elle-même en tant que valeur associée.

/// Downloads the "Medium" rendition of an asset and returns the value as a `BlogImageState`
/// Note that any error while downloading the image will result in a placeholder image
public func downloadMediumRendition(identifier: String) async -> BlogImageState {
    
    do {
        let result = try await DeliveryAPI
                                .downloadRendition(identifier: identifier,
                                                   renditionName: "Medium",
                                                   format: "jpg")
                                .downloadAsync(progress: nil)
        
        guard let uiImage = UIImage(contentsOfFile: result.result.path()) else {
            throw OracleContentError.couldNotCreateImageFromURL(result.result)
        }
        
        return .image(uiImage)
        
    } catch {
        return .image(UIImage(systemName: "questionmark.circle")!)
    }

}

Maintenant que nous disposons à la fois des informations détaillées sur le sujet et de l'image miniature, SwiftUI peut construire la représentation visuelle d'un sujet.

Cette image présente l'interface utilisateur représentant un sujet. Il contient un titre de " Comment faire ", une image miniature de tasses de café avec latte de containg et une description définissant le sujet comme apprentissage pour créer un beau art latte et verser juste la bonne tasse.

Données de liste des articles

Lorsque vous appuyez sur un sujet, l'utilisateur accède à une nouvelle page contenant la liste des articles affectés au sujet sélectionné.

La création des pages d'articles est très similaire au processus utilisé pour créer la liste des rubriques. Avec un identificateur de sujet, nous devons :

  1. Extraire la liste des articles pour ce sujet, et
  2. Pour chaque article, extraire le rendu miniature de l'actif contenu dans son champ "image".

Lors de l'extraction de la liste des ressources, notre objet de demande est .listAssets().

En l'absence de tout autre composant de générateur, toutes les ressources publiées sont extraites du canal de publication indiqué dans credentials.json. Toutefois, nous voulons extraire uniquement les ressources dont le type est OCEGettingStartedArticle et dont la propriété de sujet correspond à l'identificateur de sujet transmis.

/// Obtain the collection of articles for a given topic. Limited to a maximum of 50 articles for demo purposes.
/// - parameter topic: Asset
/// - returns: [Asset] representing the articles for the specified topic
public func fetchArticles(for topic: Asset) async throws -> [Asset] {

    let typeNode = QueryNode.equal(field: "type", value: "OCEGettingStartedArticle")
    let fieldsTopicNode = QueryNode.equal(field: "fields.topic", value: topic.identifier)
    let fullQuery = QueryBuilder(node: typeNode).and(fieldsTopicNode)
    
    let result = try await DeliveryAPI
        .listAssets()
        .query(fullQuery)
        .order(.field("fields.published_date", .desc))
        .limit(50)
        .fetchNextAsync()
    
    return result.items
}

Pour chacun des articles extraits, nous devons déterminer l'image à télécharger. Nous obtenons l'identifiant de la ressource référencée dans le champ "image" et nous l'utilisons pour soumettre une demande de téléchargement de sa miniature.

let identifier = (try article.customField("image") as Asset).identifier
let image = await self.networking.downloadThumbnail(identifier: identifier, fileGroup: article.fileGroup)

Le code réseau pour demander le téléchargement se présente comme suit :

/// Downloads the thumbnail rendition of an asset and returns the values as a ``BlogImageState``
/// Note that any error while downloading the image will result in a placeholder image
/// - parameter identifier: The identifier of the asset
/// - parameter fileGroup: The file group of the asset - used to differentiate thumbnails for digital assets, videos and "advanced videos"
public func downloadThumbnail(identifier: String, fileGroup: String) async -> BlogImageState {
    do {
        let result = try await DeliveryAPI
            .downloadThumbnail(identifier: identifier, fileGroup: fileGroup)
            .downloadAsync(progress: nil)
        
        guard let uiImage = UIImage(contentsOfFile: result.result.path()) else {
           throw OracleContentError.couldNotCreateImageFromURL(result.result)
        }
        
        return .image(uiImage)
    } catch {
        Onboarding.logError(error.localizedDescription)
        return .image(UIImage(systemName: "questionmark.circle")!)
    }
}

Nous pouvons désormais afficher un aperçu de chaque article :

Cette image présente un aperçu d'un article. Il contient un titre de " Créer un beau art latte ", une date formatée indiquant quand l'article a été publié, une image miniature de tasses de café avec un latte de containg et un texte descriptif sur l'article - que " Avec un peu de pratique, vous pouvez créer des dessins avec du lait à vapeur ".

Données d'article

Si vous appuyez sur un aperçu d'article, la page finale de l'exemple d'application s'affiche, c'est-à-dire l'article lui-même. Comme précédemment, plusieurs demandes de données doivent être effectuées :

  1. Compte tenu de l'identifiant de l'article sélectionné, nous devons récupérer ses informations détaillées.
  2. Téléchargez l'avatar de l'auteur.
  3. Téléchargez l'image de l'article à afficher.
@MainActor
func fetchArticle() async throws {

    self.article = try await self.networking.readArticle(assetId: article.identifier)
    
    let author: Asset = try self.article.customField("author")
    let authorAvatar: Asset = try author.customField("avatar")

    Task {
        self.avatar = await self.networking.downloadNative(identifier: authorAvatar.identifier)
    }
    
    Task {
        let hero: Asset = try self.article.customField("image_16x9")
        self.heroImage = await self.networking.downloadNative(identifier: hero.identifier)
    }
}

La lecture des informations détaillées d'une immobilisation est un processus simple :

/// Obtain detailed information about an Asset
/// - parameter assetId: The identifier of the asset to read
/// - returns: Asset
public func readAsset(assetId: String) async throws -> Asset {
    let result = try await DeliveryAPI
        .readAsset(assetId: assetId)
        .fetchAsync()
    
    return result
}

Télécharger l'avatar et les images d'article suivent le même schéma général que celui utilisé pour obtenir d'autres images :

/// Downloads the native rendition of an asset and returns the values as a ``BlogImageState``
/// Note that any error while downloading the image will result in a placeholder image
public func downloadNative(identifier: String) async -> BlogImageState {
    do {
        let result = try await DeliveryAPI
            .downloadNative(identifier: identifier)
            .downloadAsync(progress: nil)
        
        guard let uiImage = UIImage(contentsOfFile: result.result.path()) else {
           throw OracleContentError.couldNotCreateImageFromURL(result.result)
        }
        
        return .image(uiImage)
    } catch {
        Onboarding.logError(error.localizedDescription)
        return .image(UIImage(systemName: "questionmark.circle")!)
    }
    
}

Le résultat est un article de blog entièrement formaté :

Cette image présente un article de blog complet. Il contient des informations sur l'auteur (y compris une image d'avatar), l'image utilisée pour représenter l'article et le texte au format HTML de l'article.

Etape 3 : exécution de l'application

Une fois l'application terminée, vous pouvez l'exécuter dans le simulateur ou la déployer sur n'importe quel élément iPhone ou iPad exécutant iOS ou iPadOS 16.0 ou supérieur.

Conclusion

Dans ce tutoriel, nous avons créé un site d'application de blog iOS, qui se trouve sur GitHub. Cette application utilise Oracle Content Management comme CMS headless. Après avoir configuré Oracle Content Management avec un canal de contenu publié pour le tutoriel de blog, nous avons exécuté l'application pour extraire le contenu requis.

Pour plus d'informations sur Swift, visitez le site Web Swift.

Découvrez les principaux concepts d'Oracle Content Management dans la documentation.

Vous trouverez d'autres exemples de ce type sur la page Exemples d'Oracle Content Management dans Oracle Help Center.