NEW: Join my free 100 Days of SwiftUI challenge today! >>

Eine Petition rendern: loadHTMLString

Nach dem ganzen Parsen von JSON ist es jetzt Zeit für etwas Einfaches: wir benötigen eine Klasse für einen Detail View Controller, um den Inhalt einer Petition auf attraktive Art darzustellen.

Der einfachste Weg, um komplexe Inhalte aus dem Web zu rendern, ist fast immer die Nutzung einer WKWebView, und wir werden dieselbe Technik wie in Projekt 4 verwenden, um einen DetailViewController zu erstellen, der eine Web View enthält.

Gehe zum File-Menü und wähle New > File, dann wähle iOS > Source > Cocoa Touch Class. Klicke auf Next, nenne die Klasse "DetailViewController", und mache sie zu einer Subklasse von "UIViewController", dann klicke auf Next und Create.

Ersetze den gesamten Code von DetailViewController durch diesen:

import UIKit
import WebKit

class DetailViewController: UIViewController {
    var webView: WKWebView!
    var detailItem: Petition?

    override func loadView() {
        webView = WKWebView()
        view = webView
    }

    override func viewDidLoad() {
        super.viewDidLoad()
    }
}

Dies ist beinahe identisch zu dem Code aus Projekt 4, aber du wirst feststellen, dass ich eine Eigenschaft namens detailItem hinzugefügt habe, die unser Dictionary der Petitions-Daten enthalten wird.

Das war der einfache Teil. Der schwierige Teil besteht darin, dass wir nicht einfach den Petitions-Text in die Web View legen können, da er wahrscheinlich winzig aussehen wird. Stattdessen müssen wir ihn in etwas HTML verpacken, was eine komplett andere Sprache mit ihren eigenen Regeln und Komplexitäten ist.

Diese Reihe heißt nicht "Hacken mit HTML", daher habe ich nicht vor, hier zu tief ins Detail zu gehen. Ich sage dazu nur, dass der HTML-Code, den wir nutzen werden, iOS mitteilt, dass die Seite für mobile Geräte geeignet ist, und dass wir eine Schriftgröße verwenden wollen, die 150% größer als die Standard-Schriftgröße ist. Dieser HTML-Code wird kombiniert mit dem body-Wert unserer Petition und dann an die Web View gesendet.

Platziere dies in viewDidLoad(), direkt unterhalb des Aufrufs von super.viewDidLoad():

guard let detailItem = detailItem else { return }

let html = """
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style> body { font-size: 150%; } </style>
</head>
<body>
\(detailItem.body)
</body>
</html>
"""

webView.loadHTMLString(html, baseURL: nil)

Hier ist ein wichtiger Swift-Ausdruck drin: guard. Dies wird für eine "frühe Rückkehr" genutzt, das heißt, du richtest deinen Code so ein, dass er sofort beendet wird, wenn kritische Daten fehlen. In unserem Fall heißt das, dass detailItem in sich selbst entpackt wird, wenn es einen Wert hat, genau wie bei if let, aber wenn es aus irgendeinem Grund leer sein sollte, wird die Methode beendet.

Hinweis: Es ist ausgesprochen üblich, Variablen mit Hilfe des selben Namens zu entpacken, anstatt kleine Variationen zu verwenden. In diesem Fall hätten wir auch schreiben können, guard let unwrappedItem = detailItem, aber das macht es auch nicht einfacher.

Ich habe versucht, den HTML-Code so verständlich wie möglich zu gestalten, aber wenn dich das nicht interessiert, kümmere dich nicht drum. Worum es geht, ist, dass es einen Swift String namens html gibt, der alles enthält, um die Seite anzuzeigen, und dieser wird an die Methode loadHTMLString() der Web View übergeben, damit die Seite geladen wird. Das ist anders, als wir bisher HTML geladen haben, denn wir nutzen hier keine Webseite, sondern nur eigenen HTML-Code.

Das ist alles für den Detail View Controller, es ist wirklich so einfach. Wir müssen ihn allerdings immer noch mit dem Table View Controller verbinden, indem wir die Methode didSelectRowAt implementieren. Früher haben wir die Methode instantiateViewController() benutzt, um einen View Controller aus Main.storyboard zu laden, aber in diesem Projekt ist DetailViewController gar nicht im Storyboard - es ist einfach nur eine frei herumliegende Klasse. Das macht didSelectRowAt einfacher, da es die Klasse direkt laden kann, anstatt die Benutzeroberfläche aus einem Storyboard zu laden.

Füge also nun diese Methode zu deiner ViewController-Klasse hinzu:

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    let vc = DetailViewController()
    vc.detailItem = petitions[indexPath.row]
    navigationController?.pushViewController(vc, animated: true)
}

Lass das Projekt nun laufen, indem du Cmd+R drückst oder auf Play klickst, dann tippe auf eine Zeile, um mehr Details zu jeder Petition zu sehen. Einige Petitionen haben keinen Detail-Text, aber die meisten schon - probiere ein paar aus und schau, was du so findest.

LEARN SWIFTUI FOR FREE I have a massive, free SwiftUI video collection on YouTube teaching you how to build complete apps with SwiftUI – check it out!

MASTER SWIFT NOW
Buy Testing Swift Buy Practical iOS 12 Buy Pro Swift Buy Swift Design Patterns Buy Swift Coding Challenges Buy Server-Side Swift (Vapor Edition) Buy Server-Side Swift (Kitura Edition) Buy Hacking with macOS Buy Advanced iOS Volume One Buy Advanced iOS Volume Two Buy Hacking with watchOS Buy Hacking with tvOS Buy Hacking with Swift Buy Dive Into SpriteKit Buy Swift in Sixty Seconds Buy Objective-C for Swift Developers Buy Beyond Code

Was this page useful? Let us know!