Las aplicaciones de ejemplo son una buena manera de explorar las capacidades sin encabezado de Adobe Experience Manager AEM (). Esta aplicación para iOS AEM muestra cómo realizar consultas en el contenido mediante API de GraphQL de mediante consultas persistentes.
Ver el código fuente en GitHub
Las siguientes herramientas deben instalarse localmente:
La aplicación de iOS AEM funciona con las siguientes opciones de implementación de. Todas las implementaciones requieren lo siguiente Sitio WKND 3.0.0+ para instalar.
La aplicación de iOS está diseñada para conectarse a un AEM Publish , sin embargo, puede obtener contenido de AEM Author si la autenticación se proporciona en la configuración de la aplicación de iOS.
Clonar el adobe/aem-guides-wknd-graphql
repositorio:
$ git clone git@github.com:adobe/aem-guides-wknd-graphql.git
Launch Xcode y abra la carpeta ios-app
Modificación del archivo Config.xcconfig
archivar y actualizar AEM_SCHEME
y AEM_HOST
para que coincida con el servicio de publicación de AEM de destino.
// The http/https protocol scheme used to access the AEM_HOST
AEM_SCHEME = https
// Target hostname for AEM environment, do not include http:// or https://
AEM_HOST = publish-p123-e456.adobeaemcloud.com
Si se conecta a AEM Author, añada el AEM_AUTH_TYPE
y admitiendo propiedades de autenticación en Config.xcconfig
.
Autenticación básica
El AEM_USERNAME
y AEM_PASSWORD
AEM autentique un usuario local de la con acceso al contenido de WKND GraphQL.
AEM_AUTH_TYPE = basic
AEM_USERNAME = admin
AEM_PASSWORD = admin
Autenticación de token
El AEM_TOKEN
es un token de acceso AEM que se autentica ante un usuario de con acceso al contenido de WKND GraphQL.
AEM_AUTH_TYPE = token
AEM_TOKEN = abcd...0123
Cree la aplicación mediante Xcode e impleméntelo en el simulador de iOS.
Se debe mostrar una lista de las aventuras del sitio WKND en la aplicación. Al seleccionar una aventura, se abren los detalles de la aventura. AEM En la vista de lista de aventuras, extraiga para actualizar los datos de la vista de.
A continuación se muestra un resumen de cómo se crea la aplicación de iOS AEM, cómo se conecta a las consultas sin encabezado para recuperar contenido mediante consultas persistentes de GraphQL y cómo se presentan esos datos. El código completo se encuentra en GitHub.
AEM Siguiendo las prácticas recomendadas de las consultas sin encabezado, la aplicación de iOS AEM utiliza consultas persistentes de GraphQL para consultar datos de aventuras, de forma predeterminada, de la manera más sencilla. La aplicación utiliza dos consultas persistentes:
wknd/adventures-all
AEM consulta persistente, que devuelve todas las aventuras en con un conjunto abreviado de propiedades de, que se han guardado de forma predeterminada. Esta consulta persistente genera la lista de aventuras de la vista inicial.# Retrieves a list of all Adventures
#
# Optional query variables:
# - { "offset": 10 }
# - { "limit": 5 }
# - {
# "imageFormat": "JPG",
# "imageWidth": 1600,
# "imageQuality": 90
# }
query ($offset: Int, $limit: Int, $sort: String, $imageFormat: AssetTransformFormat=JPG, $imageWidth: Int=1200, $imageQuality: Int=80) {
adventureList(
offset: $offset
limit: $limit
sort: $sort
_assetTransform: {
format: $imageFormat
width: $imageWidth
quality: $imageQuality
preferWebp: true
}) {
items {
_path
slug
title
activity
price
tripLength
primaryImage {
... on ImageRef {
_path
_dynamicUrl
}
}
}
}
}
wknd/adventure-by-slug
consulta persistente, que devuelve una sola aventura de slug
(una propiedad personalizada que identifica de forma exclusiva una aventura) con un conjunto completo de propiedades. Esta consulta persistente activa las vistas de detalles de aventura.query ($slug: String!, $imageFormat:AssetTransformFormat=JPG, $imageSeoName: String, $imageWidth: Int=1200, $imageQuality: Int=80) {
adventureList(
filter: {slug: {_expressions: [{value: $slug}]}}
_assetTransform: {
format: $imageFormat
seoName: $imageSeoName
width: $imageWidth
quality: $imageQuality
preferWebp: true
}) {
items {
_path
title
slug
activity
adventureType
price
tripLength
groupSize
difficulty
price
primaryImage {
... on ImageRef {
_path
_dynamicUrl
}
}
description {
json
plaintext
html
}
itinerary {
json
plaintext
html
}
}
_references {
... on AdventureModel {
_path
slug
title
price
__typename
}
}
}
}
AEM Las consultas persistentes se ejecutan a través de una GET HTTP y, por lo tanto, las bibliotecas comunes de GraphQL que utilizan un POST HTTP como Apollo no se pueden utilizar. En su lugar, cree una clase personalizada que ejecute las solicitudes de GET AEM HTTP de consulta persistentes a la dirección de correo electrónico de la dirección de correo electrónico
AEM/Aem.swift
crea una instancia de Aem
AEM clase utilizada para todas las interacciones con sin encabezado El patrón es:
Cada consulta persistente tiene una función pública correspondiente (por ejemplo, getAdventures(..)
o getAdventureBySlug(..)
) las vistas de la aplicación iOS invocan para obtener datos de aventura.
La función pública llama a una función privada makeRequest(..)
que invoca una solicitud de GET AEM HTTP asíncrona a la red sin encabezado y devuelve los datos JSON.
A continuación, cada función pública descodifica los datos JSON y realiza las comprobaciones o transformaciones necesarias antes de devolver los datos de Aventura a la vista.
AEM/Models.swift
AEM , que se asignan a los objetos JSON devueltos por mi sin encabezado de la. /// # getAdventures(..)
/// Returns all WKND adventures using the `wknd-shared/adventures-all` persisted query.
/// For this func call to work, the `wknd-shared/adventures-all` query must be deployed to the AEM environment/service specified by the host.
///
/// Since HTTP requests are async, the completion syntax is used.
func getAdventures(params: [String:String], completion: @escaping ([Adventure]) -> ()) {
let request = makeRequest(persistedQueryName: "wknd-shared/adventures-all", params: params)
URLSession.shared.dataTask(with: request) { (data, response, error) in
if ((error) != nil) {
print("Unable to connect to AEM GraphQL endpoint")
completion([])
} else if (!data!.isEmpty) {
let adventures = try! JSONDecoder().decode(Adventures.self, from: data!)
DispatchQueue.main.async {
completion(adventures.data.adventureList.items)
}
}
}.resume();
}
...
/// #makeRequest(..)
/// Generic method for constructing and executing AEM GraphQL persisted queries
private func makeRequest(persistedQueryName: String, params: [String: String] = [:]) -> URLRequest {
// Encode optional parameters as required by AEM
let persistedQueryParams = params.map { (param) -> String in
encode(string: ";\(param.key)=\(param.value)")
}.joined(separator: "")
// Construct the AEM GraphQL persisted query URL, including optional query params
let url: String = "\(self.scheme)://\(self.host)/graphql/execute.json/" + persistedQueryName + persistedQueryParams;
var request = URLRequest(url: URL(string: url)!);
// Add authentication to the AEM GraphQL persisted query requests as defined by the iOS application's configuration
request = addAuthHeaders(request: request)
return request
}
...
iOS prefiere asignar objetos JSON a modelos de datos con tipo.
El src/AEM/Models.swift
define el decodificable AEM AEM Estructuras y clases de Swift que se asignan a las respuestas de JSON de la devueltas por las respuestas de JSON de la aplicación.
La interfaz de usuario de Swift se utiliza para las distintas vistas de la aplicación. Apple proporciona un tutorial de introducción para creación de listas y navegación con SwiftUI.
WKNDAdventuresApp.swift
La entrada de la solicitud e incluye AdventureListView
cuya .onAppear
el controlador de eventos se utiliza para recuperar todos los datos de aventuras mediante aem.getAdventures()
. El compartido aem
El objeto se inicializa aquí y se expone a otras vistas como un EnvironmentObject.
Views/AdventureListView.swift
Muestra una lista de aventuras (basada en los datos de aem.getAdventures()
) y muestra un elemento de lista para cada aventura con el AdventureListItemView
.
Views/AdventureListItemView.swift
Muestra todos los elementos de la lista de aventuras (Views/AdventureListView.swift
).
Views/AdventureDetailView.swift
Muestra los detalles de una aventura, incluido el título, la descripción, el precio, el tipo de actividad y la imagen principal. AEM Esta vista consulta los detalles completos de la aventura mediante el uso de: aem.getAdventureBySlug(slug: slug)
, donde la variable slug
El parámetro se pasa en función de la fila de la lista seleccionada.
AEM Las imágenes a las que hacen referencia los fragmentos de contenido de aventura las proporciona el usuario de forma. Esta aplicación de iOS utiliza la ruta _dynamicUrl
en la respuesta de GraphQL y prefija el campo AEM_SCHEME
y AEM_HOST
para crear una dirección URL completa. Si se desarrolla con el SDK de AEM, _dynamicUrl
devuelve null, por lo que para el desarrollo se debe volver al de la imagen _path
field.
AEM Si la conexión a recursos protegidos en un entorno que requiere autorización, también se deben agregar credenciales a las solicitudes de imagen.
SDWebImageSwiftUI y SDWebImage AEM se utilizan para cargar las imágenes remotas de las imágenes de aventura que se propagan desde la página de inicio de la aplicación. AdventureListItemView
y AdventureDetailView
vistas.
El aem
clase (en AEM/Aem.swift
AEM ) facilita el uso de imágenes de dos formas de uso:
aem.imageUrl(path: String)
AEM se utiliza en vistas para anteponer el esquema de la y el host a la ruta de la imagen, lo que crea una dirección URL completa.
// adventure.image() => /adobe/dynamicmedia/deliver/dm-aid--741ed388-d5f8-4797-8095-10c896dc9f1d/example.jpg?quality=80&preferwebp=true
let imageUrl = aem.imageUrl(path: adventure.image())
// imageUrl => https://publish-p123-e456.adobeaemcloud.com/adobe/dynamicmedia/deliver/dm-aid--741ed388-d5f8-4797-8095-10c896dc9f1d/example.jpg?quality=80&preferwebp=true
El convenience init(..)
in Aem
establezca encabezados de autorización HTTP en la solicitud HTTP de imagen según la configuración de las aplicaciones iOS.
/// AEM/Aem.swift
///
/// # Basic authentication init
/// Used when authenticating to AEM using local accounts (basic auth)
convenience init(scheme: String, host: String, username: String, password: String) {
...
// Add basic auth headers to all Image requests, as they are (likely) protected as well
SDWebImageDownloader.shared.setValue("Basic \(encodeBasicAuth(username: username, password: password))", forHTTPHeaderField: "Authorization")
}
/// AEM/Aem.swift
///
/// # Token authentication init
/// Used when authenticating to AEM using token authentication (Dev Token or access token generated from Service Credentials)
convenience init(scheme: String, host: String, token: String) {
...
// Add token auth headers to all Image requests, as they are (likely) protected as well
SDWebImageDownloader.shared.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
}
Se puede utilizar un enfoque similar con el nativo de SwiftUI AsyncImage. AsyncImage
es compatible con iOS 15.0+.