Bon les interfaces graphiques, on connaît (presque !) tout. Voyons maintenant comment manipuler efficacement des chaînes de caractères.
Améliorons notre navigateur
Vous vous rappelez de notre navigateur?
Si vous possédez un appareil Android avec Lollipop (ou +), vous aurez remarqué qu'en allant sur le site d'OpenClassrooms, votre barre du haut devient orange ! :) Eh non, les développeurs du site ne sont pas des magiciens, c'est une tout petite ligne de HTML qui fait ça. Par contre, si vous avez un appareil iOS et que vous allez sur Safari, la couleur ne change pas. Dans notre navigateur, nous allons faire changer la couleur de notre barre de navigation.
Allez dans Navigateur.swift, grâce à la webview, on peut récupérer le code HTML d'une page. Pour cela, on doit utiliser du JavaScript. Si vous connaissez le JavaScript, vous comprendrez tout de suite, si vous ne connaissez pas, sachez qu'un moyen pour récupérer le code HTML d'une page est le script suivant :
document.documentElement.outerHTML
Quant à la méthode qui nous permet d'exécuter du JavaScript dans une webview, la voilà :
webView.stringByEvaluatingJavaScriptFromString(string: String)
Bien sûr, il ne faut exécuter le script que lorsque la webview a fini de charger. Pour cela, on utilise la méthode webViewDidFinishLoad du UIWebViewDelegate, appelée lorsque la webview a chargé une page.
Enfin, il va falloir récupérer une chaîne de caractères à un moment donné : la méthode stringByEvaluatingJavaScriptFromString retourne une chaîne de caractères si le script doit retourner une valeur. Ici, notre script nous donne le code HTML de la page donc la méthode retourne la code HTML tel quel.
Au total, ça va donner :
//La webview a fini de charger
func webViewDidFinishLoad(webView: UIWebView) {
//On vérifie que le script ne retourne pas "nil"
if let html = webView.stringByEvaluatingJavaScriptFromString("document.documentElement.outerHTML") {
// html contient le code source de la page
}
}
Euh… Et le scanner il est où?
On y vient, enfin !
Créons une fonction func colorTopBar(htmlString: String). Le paramètre htmlString sera le code HTML de la page web.
Parcourez des chaînes avec le scanner
Comme son nom l'indique, le scanner va scanner. Et il va permettre de séparer une chaîne de caractères en plusieurs autres plus petites. Et donc de récupérer une valeur particulière.
Si vous êtes curieux vous pouvez lire le code HTML d'une page dans un navigateur en faisant clic droit > Code source de la page.
Sur la page d'OpenClassrooms, ou sur celle d'Allociné par exemple, vous remarquerez cette ligne en plus :
<meta name="theme-color" content="#E95325">
C'est cette ligne qui donne la couleur de la barre du navigateur d'Android. "E95325" est une couleur écrite en hexadécimal. Donc on veut récupérer "E95325". C'est là que l'on va utiliser notre scanner.
On va scanner la chaîne de caractères envoyée en paramètre. On va instancier une constante de type NSScanner et initialisée avec le code HTML. Ainsi, le scanner sait ce qu'il va devoir scanner :
let scan = NSScanner(string: htmlString)
Le principe du scanner est de parcourir la chaîne. Par exemple, il existe une méthode scanUpToString(string: String, intoString result: nullable) qui va faire parcourir la chaîne au scanner et s'arrêter s'il trouve "string". La fonction retourne true si le scanner trouve "string", false sinon.
On va donc écrire quelque chose comme :
func colorTopBar(htmlString: String) {
//Initialisation du scanner
let scan = NSScanner(string: htmlString)
//On regarde si htmlString contient le premier parametre
if scan.scanUpToString("<meta name=\"theme-color\" content=\"#", intoString: nil){
}
}
Donc si la chaîne contient bien le tag ce qu'on cherche, le curseur scanner s'est arrêté juste avant, c'est tout l'intérêt de "scanUpToString". Nous, on veut la valeur après le "#" donc on veut :
que le curseur s'arrête après le "#"
et scanner ce qu'il y a entre le "#" et le guillemet
scan.scanString("<meta name=\"theme-color\" content=\"#", intoString: nil)
Voilà le curseur est juste après le "#". On va réutiliser scanUpToString mais cette fois, on va utiliser la deuxième partie de la fonction, on va récupérer la partie scannée dans une variable :
var themeColor : NSString?
if scan.scanUpToString("\"", intoString: &themeColor) {
}
Le "if" est un peu superflu puisqu'un code HTML est parsemé de guillemets. On crée une variable optionnelle et on donne à cette variable la chaîne scannée par notre scanner.
Je vous passe les détails sur le reste, c'est du Swift un peu plus poussé qui manipule les hexa.
func colorTopBar(htmlString: String) {
//Initialisation du scanner
let scan = NSScanner(string: htmlString)
//On regarde si htmlString contient le premier parametre
if scan.scanUpToString("<meta name=\"theme-color\" content=\"#", intoString: nil){
//On s'arrete juste après "#"
scan.scanString("<meta name=\"theme-color\" content=\"#", intoString: nil)
var themeColor : NSString?
//On attribute la chaine scannée à themeColor
if scan.scanUpToString("\"", intoString: &themeColor) {
var themeInt : UInt32 = 0
//On initialize un nouveau scanner et on attribute l'hexa scanné à themeInt
NSScanner(string: themeColor! as String).scanHexInt(&themeInt)
//Composantes entre 0 et 255
let rouge = CGFloat((themeInt & 0xFF0000) >> 16) / 255
let vert = CGFloat((themeInt & 0x00FF00) >> 8) / 255.0
let bleu = CGFloat(themeInt & 0x0000FF) / 255.0
let color = UIColor(red: rouge, green: vert, blue: bleu, alpha: 1.0) //On anime le changement de couleurs
UIView.animateWithDuration(0.3, animations: {
Changement de couleur
self.navigationController?.navigationBar.barTintColor = color
})
}
}
}
Vous savez donc comment :
Récupérer la source HTML d'une page web
Vérifier la présence d'une chaîne de caractères via un NSScanner
Récupérer une chaîne de caractères entre deux autres
Manipulez des chaînes de caractères
Il existe beaucoup d'autres manières natives pour manipuler les chaînes de caractères.
Chaîne vide
isEmpty
retourne vrai si la chaîne est égale à "", faux sinon.
Caractères
On peut récupérer les caractères d'une chaîne via "ma chaine".characters
.
On peut utiliser le type Character : let cara : Character = "t"
.
En revanche, on doit utiliser la méthode append
pour ajouter un caractère à une chaîne :
var zut = "Zu"
zut.append(cara) // a l'aide d'un caractère
zut += "t" // avec une String
Les deux dernières lignes donnent le même résultat.
Caractères spéciaux
On écrit des caractères spéciaux à l'aide de leurs Unicodes. Exemple : let yinYang = "\u(262F)"
Taille d'une chaîne
let taille = zut.characters.count // 3
Modifier une chaîne
Insérer
var b = "Bonjour"
b.insert(" Charles", atIndex: b.endIndex) // b = Bonjour Charles
var c = "Chles"
let index = c.startIndex.advancedBy(2)
c.insert("ar", atIndex: index) // c = Charles
Ôter
var d = "adindon"
d.removeAtIndex(d.startIndex) // d = dindon
d.removeAtIndex(d.endIndex.predecessor()) // d = dindo