UIViewController — den centrala klassen i iOS-applikationer som hanterar skärmen och dess innehåll. Varje skärm på iPhone eller iPad hanteras av en ViewController som koordinerar visning, livscykel och navigering. Läs mer om UIKit-arkitekturen i officiella Apple-dokumentationen.
Huvudpunkter
UIViewController — en klass från UIKit-ramverket som hanterar UIView-hierarkin och koordinerar visningen av data på skärmen. Varje iOS-applikation innehåller minst en ViewController — rotkontrollern för fönstret. Kontrollern hanterar skärmrotationer, övergångar mellan skärmar och livscykelhändelser.
MVC-arkitekturen (Model-View-Controller) i iOS implementeras just via UIViewController: kontrollern tar emot data från modellen och uppdaterar vyn. ViewController är inget visuellt element — den hanterar egenskapen view som innehåller subview-hierarkin. Enligt Apple-data (2026) innehåller UIKit över 40 inbyggda underklasser av UIViewController.
Den första iPhone SDK (2008) inkluderade UIViewController med tre livscykelmetoder. Under 18 år har Apple lagt till stöd för Container View Controller, adaptiva presentationer, UIViewControllerTransitioningDelegate för anpassade animationer och delad skärm på iPad. UIViewController förblir en obligatorisk komponent för UIKit-applikationer.
Livscykeln för UIViewController — en sekvens av metoder som anropas av systemet när skärmen skapas, visas och döljs. Att förstå livscykeln är avgörande: felaktig placering av kod leder till minnesläckor, onödiga nätverksförfrågningar och flimmer i gränssnittet.
| Metod | Anropstillfälle | Syfte |
|---|---|---|
| viewDidLoad | En gång, efter att view laddats i minnet | Inledande UI-konfiguration, Combine-prenumeration |
| viewWillAppear | Innan skärmen visas | Datauppdatering, dölj/visa navigeringsfält |
| viewDidAppear | Efter att skärmen visas | Starta animationer, analys, kamerauppdatering |
| viewWillDisappear | Innan skärmen lämnas | Spara utkast, avsluta prenumeration på notiser |
| viewDidDisappear | Efter att skärmen lämnats | Stoppa tunga processer, frigöra resurser |
Vid första visningen av skärmen: init → loadView → viewDidLoad → viewWillAppear → viewDidAppear. Vid återkomst (återvändo från en annan skärm): viewWillAppear → viewDidAppear. viewDidLoad anropas endast en gång under kontrollerns livstid.
Metoden viewDidLoad — den huvudsakliga punkten för konfiguration av användargränssnittet. Anropas efter att view laddats i minnet, när alla IBOutlet är anslutna. Här skapas UI-element programmatiskt, begränsningar konfigureras och initial data laddas.
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)
}
}I SwiftUI är denna kod motsvarigheten till View-kroppen. Men UIViewController ger full kontroll över livscykeln och optimering. bindViewModel använder Combine för reaktiv prenumeration — data uppdateras automatiskt när modellen ändras.
viewWillAppear anropas varje gång innan skärmen visas, även om den redan fanns i minnet. Detta är platsen för att uppdatera data som kan ha ändrats på en annan skärm: ladda om listan, uppdatera notisräknaren, konfigurera navigeringsfältet för en specifik skärm.
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// Dölj navigeringsfältet på denna skärm
navigationController?.setNavigationBarHidden(true, animated: animated)
// Uppdatera data vid återkomst från en annan skärm
tableView.reloadData()
badgeLabel.text = "\(CartManager.shared.itemCount)"
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
// Analys: först efter att användaren sett skärmen
AnalyticsService.shared.logScreenView("Profile")
}Skillnaden mellan viewDidLoad och viewWillAppear är avgörande: viewDidLoad körs en gång och lämpar sig för statisk konfiguration, viewWillAppear — varje gång vid visning, lämpar sig för dynamiska uppdateringar. Att placera nätverksförfrågningar i viewDidLoad leder till visning av inaktuell data vid återkomst till skärmen.
Container View Controller — en ViewController som hanterar en eller flera underordnade ViewControllers. Apple tillhandahåller tre inbyggda containrar: UINavigationController (skärmstack), UITabBarController (flikar) och UISplitViewController (master-detail för iPad).
UINavigationController organiserar övergångar i en stack — push lägger till en skärm, pop tar bort. UITabBarController växlar mellan oberoende sektioner av applikationen. UISplitViewController visar två kontrollerer sida vid sida på iPad och en på iPhone. Utvecklaren kan skapa sin egen container via addChild.
// Anpassad Container View Controller
final class ContainerViewController: UIViewController {
private let sidebarVC = SidebarViewController()
private let contentVC = ContentViewController()
override func viewDidLoad() {
super.viewDidLoad()
// Lägga till underordnad kontroller
addChild(sidebarVC)
view.addSubview(sidebarVC.view)
sidebarVC.didMove(toParent: self)
addChild(contentVC)
view.addSubview(contentVC.view)
contentVC.didMove(toParent: self)
}
}Korrekt arbete med Container View Controller kräver anrop av addChild, tillägg av view och didMove(toParent:) i denna ordning. Vid borttagning — willMove(toParent: nil), removeFromSuperview, removeFromParent. Att bryta ordningen leder till minnesläckor.
Problemet med Massive View Controller — när UIViewController innehåller hundratals rader kod med affärslogik, nätverksförfrågningar, navigering och UI-kod. Apple är medveten om problemet och rekommenderar MVVM (Model-View-ViewModel) tillsammans med Coordinator för att separera navigeringen.
MVVM flyttar affärslogiken från kontrollern till ViewModel. Controller kopplar bara ViewModel till View via Combine eller delegat. Coordinator separerar navigeringslogiken — skapande och övergångar mellan kontrollerer — i en separat klass. Detta tillvägagångssätt har inkluderats i Apples bästa praxis sedan 2024.
// Coordinator — hantering av navigering
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)
}
}Valet mellan UIViewController och SwiftUI View beror på projektets startår, anpassningskrav och lägsta version av iOS som stöds. UIKit med UIViewController förblir grunden för projekt som påbörjades före 2020 och för applikationer med djup anpassning av gränssnittet.
SwiftUI passar för nya projekt med iOS 17+, standardgränssnitt och prototyper. Men för anpassade övergångar, arbete med kamera, MapKit, komplexa CALayer-animationer krävs UIViewController. Apple rekommenderar att kombinera tillvägagångssätt via UIHostingController (SwiftUI i UIKit) och UIViewRepresentable (UIKit i SwiftUI).
| Scenario | UIKit (UIViewController) | SwiftUI (View) |
|---|---|---|
| Anpassad animation | Fullständig kontroll via UIViewPropertyAnimator | Begränsad via Animation |
| Arbete med kamera | AVCaptureSession + UIViewPreview | Via UIViewControllerRepresentable |
| CollectionView | UICollectionView + UICollectionViewLayout | LazyVGrid/LazyHGrid |
| iPad-anpassning | UISplitViewController + UITraitCollection | NavigationSplitView + sizeClass |
| Utvecklingshastighet | Långsammare (manuell layout) | Snabbare (deklarativ) |
Vanliga frågor
UIViewController — kontroller som hanterar skärmen och dess livscykel. UIView — vy som visar innehåll. ViewController innehåller en UIView-hierarki, men är själv inget visuellt element. En kontroller hanterar många vyer.
Massive View Controller — ett anti-mönster när UIViewController innehåller för mycket logik: data, navigering, nätverksförfrågningar, animationer. Lösning — separera koden i separata tjänster, koordinatorer och ViewModel (MVVM).
Fyra sätt: via egenskap vid prepare(for:sender:) (Segue), via delegat (Delegate), via closure (Closure), via en delad tjänst. För lös koppling används Coordinator + Delegate eller Combine.
Container View Controller — en kontroller som hanterar underordnade ViewControllers. Exempel: UINavigationController, UITabBarController, UISplitViewController. Föräldrakontrollern lägger till barn via addChild, växlar mellan dem och hanterar deras layout.
UIViewController — för komplexa anpassade animationer, arbete med kamera, karta, video, UICollectionView med anpassad layout. SwiftUI View — för standardgränssnitt iOS 13+. Kombinering via UIHostingController är tillåten.
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.
Läs också