UIViewController ist die zentrale Klasse von iOS-Anwendungen, die den Bildschirm und seinen Inhalt verwaltet. Jeder iPhone- oder iPad-Bildschirm wird von einem ViewController verwaltet, der Anzeige, Lebenszyklus und Navigation koordiniert. Weitere Informationen zur UIKit-Architektur finden Sie in der offiziellen Apple-Dokumentation.
Wichtige Punkte
UIViewController ist eine Klasse aus dem UIKit-Framework, die eine Hierarchie von UIView verwaltet und die Anzeige von Daten auf dem Bildschirm koordiniert. Jede iOS-Anwendung enthält mindestens einen ViewController — den Root-Controller des Fensters. Der Controller behandelt Bildschirmdrehungen, Übergänge zwischen Bildschirmen und Lebenszyklusereignisse.
Die MVC-Architektur (Model-View-Controller) in iOS wird genau durch UIViewController implementiert: Der Controller empfängt Daten vom Modell und aktualisiert die Ansicht. Ein ViewController ist kein visuelles Element — er verwaltet die View-Eigenschaft, die eine Hierarchie von Subviews enthält. Laut Apple (2026) enthält UIKit mehr als 40 integrierte UIViewController-Unterklassen.
Das erste iPhone SDK (2008) enthielt UIViewController mit drei Lebenszyklusmethoden. In 18 Jahren fügte Apple Unterstützung für Container View Controller, adaptive Präsentationen, UIViewControllerTransitioningDelegate für benutzerdefinierte Animationen und den geteilten Bildschirmmodus auf dem iPad hinzu. UIViewController bleibt eine obligatorische Komponente für UIKit-Anwendungen.
Der Lebenszyklus von UIViewController ist eine Sequenz von Methoden, die vom System beim Erstellen, Anzeigen und Ausblenden eines Bildschirms aufgerufen werden. Das Verständnis des Lifecycle ist entscheidend: Eine falsche Platzierung von Code führt zu Speicherlecks, unnötigen Netzwerkanfragen und flackernder Benutzeroberfläche.
| Methode | Aufrufzeitpunkt | Zweck |
|---|---|---|
| viewDidLoad | Einmal, nachdem die View in den Speicher geladen wurde | Erstmalige UI-Einrichtung, Combine-Abonnement |
| viewWillAppear | Vor dem Erscheinen des Bildschirms | Datenaktualisierung, Navigationsleiste aus-/einblenden |
| viewDidAppear | Nach dem Erscheinen des Bildschirms | Animationen starten, Analysen, Kameraaktualisierung |
| viewWillDisappear | Vor dem Verlassen des Bildschirms | Entwürfe speichern, Benachrichtigungen abbestellen |
| viewDidDisappear | Nach dem Verlassen des Bildschirms | Schwere Prozesse stoppen, Ressourcen freigeben |
Bei der ersten Anzeige des Bildschirms lautet die Sequenz: init → loadView → viewDidLoad → viewWillAppear → viewDidAppear. Beim erneuten Erscheinen (Rückkehr von einem anderen Bildschirm): viewWillAppear → viewDidAppear. viewDidLoad wird nur einmal während der Lebensdauer des Controllers aufgerufen.
Die Methode viewDidLoad ist der Hauptpunkt für die Konfiguration der Benutzeroberfläche. Sie wird aufgerufen, nachdem die View in den Speicher geladen wurde, wenn alle IBOutlet-Verbindungen bereits hergestellt sind. Hier werden UI-Elemente programmgesteuert erstellt, Constraints konfiguriert und Anfangsdaten geladen.
final class ProfileViewController: UIViewController {
private let tableView = UITableView()
private let viewModel = ProfileViewModel()
override func viewDidLoad() {
super.viewDidLoad()
setupUI()
bindViewModel()
}
private func setupUI() {
view.addSubview(tableView)
tableView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
tableView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
])
tableView.register(ProfileCell.self,
forCellReuseIdentifier: ProfileCell.reuseId)
}
private func bindViewModel() {
viewModel.$user
.receive(on: DispatchQueue.main)
.sink { [weak self] user in
self?.title = user.name
}
.store(in: &cancellables)
}
}In SwiftUI entspricht dieser Code dem Body der View. Aber UIViewController bietet volle Kontrolle über den Lebenszyklus und die Optimierung. bindViewModel verwendet Combine für reaktives Abonnement — Daten werden automatisch aktualisiert, wenn sich das Modell ändert.
viewWillAppear wird jedes Mal vor dem Erscheinen des Bildschirms aufgerufen, auch wenn er bereits im Speicher ist. Dies ist der Ort, um Daten zu aktualisieren, die sich auf einem anderen Bildschirm geändert haben könnten: Neuladen einer Liste, Aktualisieren des Benachrichtigungs-Badges, Konfigurieren der Navigationsleiste für einen bestimmten Bildschirm.
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// Navigationsleiste auf diesem Bildschirm ausblenden
navigationController?.setNavigationBarHidden(true, animated: animated)
// Daten bei Rückkehr von einem anderen Bildschirm aktualisieren
tableView.reloadData()
badgeLabel.text = "\(CartManager.shared.itemCount)"
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
// Analyse: erst nachdem der Benutzer den Bildschirm gesehen hat
AnalyticsService.shared.logScreenView("Profile")
}Der Unterschied zwischen viewDidLoad und viewWillAppear ist entscheidend: viewDidLoad wird einmal ausgeführt und eignet sich für statische Einrichtung, viewWillAppear wird jedes Mal ausgeführt, wenn der Bildschirm angezeigt wird, und eignet sich für dynamische Aktualisierungen. Das Platzieren von Netzwerkanfragen in viewDidLoad führt dazu, dass beim Zurückkehren zum Bildschirm veraltete Daten angezeigt werden.
Container View Controller ist ein ViewController, der einen oder mehrere untergeordnete ViewControllers verwaltet. Apple bietet drei integrierte Container: UINavigationController (Bildschirmstapel), UITabBarController (Registerkarten) und UISplitViewController (Master-Detail für iPad).
UINavigationController organisiert Übergänge in einem Stapel — Push fügt einen Bildschirm hinzu, Pop entfernt ihn. UITabBarController wechselt zwischen unabhängigen Abschnitten der Anwendung. UISplitViewController zeigt auf dem iPad zwei Controller nebeneinander und auf dem iPhone einen an. Ein Entwickler kann über addChild einen benutzerdefinierten Container erstellen.
// Benutzerdefinierter Container View Controller
final class ContainerViewController: UIViewController {
private let sidebarVC = SidebarViewController()
private let contentVC = ContentViewController()
override func viewDidLoad() {
super.viewDidLoad()
// Hinzufügen eines untergeordneten Controllers
addChild(sidebarVC)
view.addSubview(sidebarVC.view)
sidebarVC.didMove(toParent: self)
addChild(contentVC)
view.addSubview(contentVC.view)
contentVC.didMove(toParent: self)
}
}Die korrekte Arbeit mit Container View Controller erfordert das Aufrufen von addChild, das Hinzufügen der View und didMove(toParent:) in dieser Reihenfolge. Beim Entfernen: willMove(toParent: nil), removeFromSuperview, removeFromParent. Die Verletzung der Reihenfolge führt zu Speicherlecks.
Das Problem des Massive View Controller tritt auf, wenn ein UIViewController Hunderte von Codezeilen mit Geschäftslogik, Netzwerkanfragen, Navigation und UI-Code enthält. Apple erkennt das Problem an und empfiehlt MVVM (Model-View-ViewModel) zusammen mit Coordinator zur Auslagerung der Navigation.
MVVM verschiebt die Geschäftslogik vom Controller in eine ViewModel. Der Controller bindet nur die ViewModel über Combine oder einen Delegaten an die View. Coordinator lagert die Navigationslogik — Erstellung und Übergang zwischen Controllern — in eine separate Klasse aus. Dieser Ansatz wurde 2024 in die Apple-Best Practices aufgenommen.
// Coordinator — Navigationsverwaltung
protocol Coordinator {
var childCoordinators: [Coordinator] { get set }
func start()
}
final class MainCoordinator: Coordinator {
var childCoordinators = [Coordinator]()
private let navigationController: UINavigationController
init(navigationController: UINavigationController) {
self.navigationController = navigationController
}
func start() {
let vc = ListViewController()
vc.didSelectItem = { [weak self] item in
self?.showDetail(item)
}
navigationController.pushViewController(vc, animated: false)
}
private func showDetail(_ item: Item) {
let vc = DetailViewController(item: item)
navigationController.pushViewController(vc, animated: true)
}
}Die Wahl zwischen UIViewController und SwiftUI View hängt vom Startjahr des Projekts, den Anpassungsanforderungen und der mindestens unterstützten iOS-Version ab. UIKit mit UIViewController bleibt die Grundlage für Projekte, die vor 2020 gestartet wurden, und für Anwendungen mit tiefer Oberflächenanpassung.
SwiftUI eignet sich für neue Projekte mit iOS 17+, Standardschnittstellen und Prototypen. Für benutzerdefinierte Übergänge, Kameraarbeit, MapKit und komplexe CALayer-Animationen ist jedoch UIViewController erforderlich. Apple empfiehlt, Ansätze über UIHostingController (SwiftUI in UIKit) und UIViewRepresentable (UIKit in SwiftUI) zu kombinieren.
| Szenario | UIKit (UIViewController) | SwiftUI (View) |
|---|---|---|
| Benutzerdefinierte Animation | Vollständige Kontrolle über UIViewPropertyAnimator | Eingeschränkt durch Animation |
| Kameraarbeit | AVCaptureSession + UIViewPreview | Über UIViewControllerRepresentable |
| CollectionView | UICollectionView + UICollectionViewLayout | LazyVGrid/LazyHGrid |
| iPad-Anpassung | UISplitViewController + UITraitCollection | NavigationSplitView + sizeClass |
| Entwicklungsgeschwindigkeit | Langsamer (manuelles Layout) | Schneller (deklarativ) |
Häufig gestellte Fragen
UIViewController ist ein Controller, der den Bildschirm und seinen Lebenszyklus verwaltet. UIView ist eine Ansicht, die Inhalte anzeigt. Ein ViewController enthält eine Hierarchie von UIViews, ist aber selbst kein visuelles Element. Ein Controller verwaltet mehrere Ansichten.
Massive View Controller ist ein Antipattern, bei dem UIViewController zu viel Logik enthält: Daten, Navigation, Netzwerkanfragen, Animation. Die Lösung besteht darin, Code in separate Dienste, Koordinatoren und ViewModel (MVVM) auszulagern.
Vier Wege: über eine Eigenschaft in prepare(for:sender:) (Segue), über einen Delegaten (Delegate), über einen Closure (Closure), über einen gemeinsamen Dienst. Für lose Kopplung verwenden Sie Coordinator + Delegate oder Combine.
Container View Controller ist ein Controller, der untergeordnete ViewControllers verwaltet. Beispiele: UINavigationController, UITabBarController, UISplitViewController. Der übergeordnete Controller fügt Kinder über addChild hinzu, wechselt zwischen ihnen und verwaltet ihr Layout.
UIViewController — für komplexe benutzerdefinierte Animationen, Kameraarbeit, Karten, Videos, UICollectionView mit benutzerdefiniertem Layout. SwiftUI View — für Standardschnittstellen ab iOS 13+. Die Kombination über UIHostingController ist akzeptabel.
Zusammenfassung
Wir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.
Lesen Sie auch