iOS
[AEM as a Cloud Service]{class="badge informative"}
Exempelprogram är ett bra sätt att utforska Adobe Experience Manager headless-funktioner (AEM). I det här iOS-programmet visas hur du använder AEM GraphQL API:er med beständiga frågor.
Visa källkoden på GitHub
Förutsättningar prerequisites
Följande verktyg bör installeras lokalt:
AEM
IOS fungerar med följande AEM driftsättningsalternativ. Alla distributioner kräver att WKND-platsen v3.0.0+ är installerad.
- AEM as a Cloud Service
- Lokal konfiguration med AEM Cloud Service SDK
IOS-programmet är utformat för att ansluta till en AEM Publish -miljö, men det kan hämta innehåll från AEM författare om autentisering anges i iOS-programmets konfiguration.
Så här använder du
-
Klona
adobe/aem-guides-wknd-graphql
-databasen:code language-shell $ git clone git@github.com:adobe/aem-guides-wknd-graphql.git
-
Öppna Xcode och öppna mappen
ios-app
-
Ändra filen
Config.xcconfig
och uppdateraAEM_SCHEME
ochAEM_HOST
så att de matchar AEM Publish-tjänst.code language-plain // 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
Om du ansluter till AEM författare lägger du till autentiseringsegenskaperna
AEM_AUTH_TYPE
och tillhörande autentiseringsegenskaper iConfig.xcconfig
.Grundläggande autentisering
AEM_USERNAME
ochAEM_PASSWORD
autentiserar en lokal AEM med åtkomst till WKND GraphQL-innehåll.code language-plain AEM_AUTH_TYPE = basic AEM_USERNAME = admin AEM_PASSWORD = admin
Tokenautentisering
AEM_TOKEN
är en åtkomsttoken som autentiserar en AEM användare med åtkomst till WKND GraphQL-innehåll.code language-plain AEM_AUTH_TYPE = token AEM_TOKEN = abcd...0123
-
Bygg applikationen med Xcode och distribuera den till iOS-simulatorn
-
En lista över äventyr från WKND-webbplatsen ska visas i programmet. Om du väljer ett äventyr öppnas äventyrsinformationen. Uppdatera data från AEM genom att dra i äventyrslistvyn.
Koden
Nedan följer en sammanfattning av hur iOS-programmet byggs, hur det ansluter till AEM Headless för att hämta innehåll med GraphQL beständiga frågor och hur dessa data presenteras. Den fullständiga koden finns på GitHub.
Beständiga frågor
Efter AEM Headless-metodtips använder iOS-programmet AEM GraphQL beständiga frågor för att fråga efter äventyrsdata. Programmet använder två beständiga frågor:
wknd/adventures-all
beständig fråga, som returnerar alla äventyr i AEM med en förkortad uppsättning egenskaper. Den här beständiga frågan styr den inledande vyns äventyrslista.
# 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
beständig fråga, som returnerar ett enskilt äventyr frånslug
(en anpassad egenskap som unikt identifierar ett äventyr) med en fullständig uppsättning egenskaper. Den här beständiga frågan styr äventyrsdetaljvyerna.
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
}
}
}
}
Kör GraphQL beständig fråga
AEM beständiga frågor körs via HTTP-GET och därför kan vanliga GraphQL-bibliotek som använder HTTP-POST som Apollo inte användas. Skapa i stället en anpassad klass som kör den beständiga frågan från HTTP GET till AEM.
AEM/Aem.swift
instansierar klassen Aem
som används för alla interaktioner med AEM Headless. Mönstret är:
-
Varje beständig fråga har en motsvarande offentlig funktion (t.ex.
getAdventures(..)
ellergetAdventureBySlug(..)
) iOS-programmets vyer anropas för att hämta äventyrsdata. -
Funktionen public anropar en privat funktion
makeRequest(..)
som anropar en asynkron HTTP GET-begäran för AEM Headless och returnerar JSON-data. -
Varje offentlig funktion avkodar sedan JSON-data och utför alla nödvändiga kontroller eller omvandlingar innan Adventure-data returneras till vyn.
- AEM GraphQL JSON-data avkodas med hjälp av de strukturer/klasser som definieras i
AEM/Models.swift
, som mappas till JSON-objekten som returnerade min AEM Headless.
- AEM GraphQL JSON-data avkodas med hjälp av de strukturer/klasser som definieras i
/// # 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
}
...
GraphQL svarsdatamodeller
iOS föredrar att mappa JSON-objekt till datamodeller.
src/AEM/Models.swift
definierar de decoeable Swift-strukturer och klasser som mappas till de AEM JSON-svar som returneras genom AEM JSON-svar.
Vyer
SwiftUI används för de olika vyerna i programmet. I Apple finns en självstudiekurs för att komma igång med skapa listor och navigering med SwiftUI.
-
WKNDAdventuresApp.swift
Programposten och innehåller
AdventureListView
vars.onAppear
-händelsehanterare används för att hämta alla äventyrsdata viaaem.getAdventures()
. Det deladeaem
-objektet initieras här och exponeras för andra vyer som ett EnvironmentObject. -
Views/AdventureListView.swift
Visar en lista med äventyr (baserat på data från
aem.getAdventures()
) och visar ett listobjekt för varje äventyr med hjälp avAdventureListItemView
. -
Views/AdventureListItemView.swift
Visar varje objekt i äventyrslistan (
Views/AdventureListView.swift
). -
Views/AdventureDetailView.swift
Visar information om ett äventyr, inklusive titel, beskrivning, pris, aktivitetstyp och primär bild. Den här vyn AEM om du vill ha fullständig äventyrsinformation med hjälp av
aem.getAdventureBySlug(slug: slug)
, där parameternslug
skickas baserat på urvalslisteraden.
Fjärrbilder
Bilder som refereras av äventyrliga innehållsfragment hanteras av AEM. Den här iOS-appen använder sökvägsfältet _dynamicUrl
i GraphQL-svaret och prefixerar AEM_SCHEME
och AEM_HOST
för att skapa en fullständigt kvalificerad URL. Om du utvecklar mot AE SDK returnerar _dynamicUrl
null, så för utveckling återgår du till bildens _path
-fält.
Om du ansluter till skyddade resurser på AEM som kräver auktorisering, måste autentiseringsuppgifter också läggas till i bildbegäranden.
SDWebImageSwiftUI och SDWebImage används för att läsa in fjärrbilder från AEM som fyller i Adventure-bilden i vyerna AdventureListItemView
och AdventureDetailView
.
Klassen aem
(i AEM/Aem.swift
) underlättar användningen av AEM bilder på två sätt:
-
aem.imageUrl(path: String)
används i vyer för att lägga till prepend-schemat för AEM och vara värd för bildens sökväg, vilket skapar en fullständigt kvalificerad URL.code language-swift // 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
-
convenience init(..)
iAem
anger rubriker för HTTP-auktorisering på avbildningens HTTP-begäran, baserat på iOS-programkonfigurationen.- Om grundläggande autentisering har konfigurerats bifogas grundläggande autentisering till alla bildbegäranden.
code language-swift /// 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") }
- Om tokenautentisering har konfigurerats kopplas tokenautentisering till alla bildbegäranden.
code language-swift /// 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") }
- Om ingen autentisering har konfigurerats bifogas ingen autentisering till bildbegäranden.
En liknande metod kan användas med SwiftUI-inbyggt AsyncImage. AsyncImage
stöds i iOS 15.0+.