MVC (Model-View-Controller) — architektonický vzor, který rozděluje aplikaci na tři komponenty: Model odpovídá za data a obchodní logiku, View — za uživatelské rozhraní, Controller — za zpracování vstupu a koordinaci Modelu a View. V iOS je MVC implementován přes UIViewController, v Android — přes Activity a Fragment. MVC zůstává základním vzorem, na kterém jsou postaveny MVVM, MVP a Clean Architecture. Více — na MVC in Cocoa Core.
Hlavní body
MVC (Model-View-Controller) — architektonický vzor navržený Trygve Reenskaugem v roce 1979 pro jazyk Smalltalk-80. Vzor rozděluje aplikaci na tři vrstvy: Model obsahuje data a obchodní logiku, View odpovídá za zobrazení, Controller zpracovává uživatelský vstup a aktualizuje Model a View. Oddělení odpovědností umožňuje měnit každou vrstvu nezávisle — například nahradit View z UIKit na SwiftUI bez změny obchodní logiky v Modelu.
Interakce komponent v MVC sleduje cyklus: uživatel interaguje s View → Controller obdrží událost → Controller aktualizuje Model → Model informuje Controller o změnách → Controller aktualizuje View. V klasické implementaci Model používá vzor Observer: při změně dat Model rozesílá oznámení, Controller se přihlásí k odběru a aktualizuje View. V implementaci Apple plní tuto roli Key-Value Observing (KVO) nebo NotificationCenter.
| Komponenta | Odpovědnost | Příklad v iOS | Příklad v Android |
|---|---|---|---|
| Model | Data, obchodní logika, síť | Struct User, CoreData | Data class, Repository |
| View | Zobrazení UI | Storyboard, XIB, UIView | XML rozvržení, Jetpack Compose |
| Controller | Zpracování vstupu, koordinace | UIViewController | Activity, Fragment |
MVC v moderním vývoji mobilních aplikací se používá méně než před 10 lety, ale zůstává povinný k pochopení. Apple doporučuje MVC pro jednoduché obrazovky v UIKit aplikacích. Google nedoporučuje čisté MVC pro Android — oficiální dokumentace navrhuje MVVM s Jetpack. Znalost MVC je však nezbytná pro práci s legacy projekty a pro pochopení evoluce architektonických vzorů.
Apple MVC — vlastní implementace vzoru zabudovaná do UIKit. UIViewController plní roli Controlleru: spravuje životní cyklus obrazovky (viewDidLoad, viewWillAppear, viewDidDisappear), zpracovává dotyky a akce uživatele, aktualizuje View přes IBOutlets. View je vytvořeno v Interface Builder (storyboard nebo XIB) nebo programově. Model — jakékoli datové objekty: síťové služby, CoreData zásobníky, Swift struktury.
final class UserViewController: UIViewController {
// View (přes storyboard outlet)
@IBOutlet private var nameLabel: UILabel!
@IBOutlet private var emailLabel: UILabel!
// Model
private let userService = UserService()
override func viewDidLoad() {
super.viewDidLoad()
loadUser()
}
private func loadUser() {
userService.fetchUser { [weak self] user in
// Controller aktualizuje View
self?.nameLabel.text = user.name
self?.emailLabel.text = user.email
}
}
}
Problém Apple MVC — View a Controller jsou úzce propojeny. UIViewController současně spravuje View i logiku. Storyboard ukládá View v XML, ale kontroler má přímé reference na UI prvky přes IBOutlets. To porušuje princip jediné odpovědnosti: kontroler odpovídá za životní cyklus, delegáty, datasource, target-action a animace. Výsledkem je, že standardní obrazovka iOS aplikace obsahuje 200–500 řádků v kontroleru.
Životní cyklus ViewController — Apple poskytuje 6 metod životního cyklu: loadView (ruční vytvoření View), viewDidLoad (po načtení View do paměti), viewWillAppear (před zobrazením na obrazovce), viewDidAppear (po animaci), viewWillDisappear (před opuštěním obrazovky), viewDidDisappear (po opuštění). Každá metoda — místo pro umístění logiky v MVC. Používání těchto metod pro obchodní logiku urychluje růst kontroleru.
Android MVC — Activity a Fragment plní roli Controlleru, XML soubory rozvržení — View, jakákoli třída POJO s daty — Model. Activity spravuje životní cyklus obrazovky: onCreate, onStart, onResume, onPause, onStop, onDestroy. Fragment — pod-obrazovka uvnitř Activity s vlastním životním cyklem. View (XML) je odděleno od Controlleru a načítá se přes setContentView nebo LayoutInflater. Model — repozitáře, databáze, síťová volání.
class UserActivity : AppCompatActivity() {
// View přes XML rozvržení
private lateinit var binding: ActivityUserBinding
// Model
private val userRepository = UserRepository()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityUserBinding.inflate(layoutInflater)
setContentView(binding.root)
loadUser()
}
private fun loadUser() {
userRepository.getUser { user ->
runOnUiThread {
binding.nameText.text = user.name
binding.emailText.text = user.email
}
}
}
}
Android ViewBinding a DataBinding — moderní nástroje snižující provázanost Controlleru a View. ViewBinding generuje třídu s přímými referencemi na View z XML, odstraňuje findViewById. DataBinding přidává možnost vázání dat s UI v XML značkách přes @{user.name}. DataBinding — krok směrem k MVVM, protože umožňuje přenášet data z Modelu do View bez kódu v Activity. Google doporučuje DataBinding pro všechny nové projekty.
Životní cyklus Android je složitější než iOS: Activity může být zničena a znovu vytvořena při otočení obrazovky, nedostatku paměti nebo změně konfigurace. V čistém MVC kontroler (Activity) obsahuje logiku, která se při zničení ztrácí. To vyžaduje ukládání stavu přes onSaveInstanceState nebo ViewModel z Jetpack, což přesahuje rámec čistého MVC a přibližuje architekturu k MVVM.
Massive View Controller — termín popisující hlavní problém MVC ve vývoji mobilních aplikací. Kontroler v iOS a Android přebírá příliš mnoho odpovědností: zpracování vstupu, validace dat, síťová interakce, navigace, ukládání do mezipaměti, animace, správa životního cyklu. Výsledkem je, že kontroler naroste na 500–2000 řádků kódu, stává se obtížně čitelným, testovatelným a udržovatelným.
Příčiny Massive View Controller — architektura UIKit a Android Framework podporuje umístění logiky do kontroleru. Síťová volání, zpracování JSON, navigace — vše se přirozeně píše v Activity nebo UIViewController, protože mají přístup k životnímu cyklu a UI. Vývojář musí vědomě přesouvat logiku do samostatných tříd (Service, Manager, Interactor), což vyžaduje disciplínu a pochopení architektonických principů.
| Problém MVC | Popis | Řešení |
|---|---|---|
| Silná provázanost | Controller zná View a Model | MVVM — ViewModel nezná View |
| Obtížnost testování | Controller závisí na UIKit/Android | Přesun logiky do služeb |
| Životní cyklus | Stav se ztrácí při otočení | ViewModel z Jetpack/SwiftUI |
| Nedostatek navigace | Controller spravuje přechody | Vzor Coordinator, Router |
Testování MVC — Model se testuje izolovaně unit testy. Controller je obtížné testovat kvůli závislosti na UIKit/UIFoundation. XCTest neumožňuje vytvořit UIViewController bez okna zobrazení. Pro Android ActivityTestRule a Robolectric částečně řeší problém, ale testy jsou pomalé. View se obvykle netestuje unit testy — pro UI se používají snímkové a UI testy (XCUITest, Espresso).
Kdy je MVC oprávněný — jednoduché obrazovky z jednoho-dvou prvků (přihlašovací obrazovka, profil, nastavení). Prototypy a MVP pro ověření hypotéz — MVC se píše rychleji bez dalších vrstev. Projekty s malou kódovou základnou do 10–15 obrazovek. Ve složitých projektech MVC vede k hromadění technického dluhu a vyžaduje refaktoring každých 6–12 měsíců.
MVC vs MVVM — hlavní rozdíl: v MVVM je kontroler nahrazen ViewModelem, který nemá referenci na View. Data jsou přenášena přes Observable (SwiftUI), LiveData/StateFlow (Android) nebo Combine/RxSwift. ViewModel se testuje unit testy bez UI závislostí. Apple doporučuje MVVM se SwiftUI od roku 2019, Google — MVVM s LiveData/Flow jako oficiální architekturu Android. MVVM vyžaduje více kódu pro vázání, ale výrazně zlepšuje testovatelnost.
MVC vs MVP — v MVP (Model-View-Presenter) je Presenter testovatelná vrstva, která přijímá View přes rozhraní. Na rozdíl od MVC, kde Controller přímo spravuje View přes UIKit, Presenter nezávisí na frameworku — pracuje přes abstrakci ViewInterface. MVP byl populární ve vývoji Android do příchodu Jetpack a používá se ve starých projektech. Presenter žije déle než Activity a zachovává stav při otočení obrazovky.
MVC vs Clean Architecture — Clean Architecture přidává vrstvy Use Cases (Interactors), Entities, Gateways a Repository. MVC zůstává v prezentační vrstvě, ale obchodní logika je přesunuta do doménové vrstvy s Use Cases. Clean Architecture řeší problém Massive View Controller radikálně — Controller obsahuje pouze volání Use Cases a aktualizaci View. Nevýhodou je výrazné zvýšení počtu tříd a souborů, což je oprávněné pro projekty od 50+ obrazovek.
// MVC v iOS: Controller obsahuje vše
class OrderViewController: UIViewController {
func placeOrder() {
// Validace + síť + UI aktualizace
guard Validation.isValid(total) else { return }
NetworkService.shared.submit(order) { [weak self] result in
self?.handleResult(result)
}
}
}
// MVVM: logika ve ViewModelu
class OrderViewModel: ObservableObject {
@Published var state: OrderState = .idle
func placeOrder() { /* obchodní logika */ }
}
Výběr architektury závisí na velikosti týmu, projektu a požadované testovatelnosti. Pro tým 1–2 vývojářů a projekt do 20 obrazovek je vhodný MVVM. Pro velký tým od 5 vývojářů a projekt od 50 obrazovek — Clean Architecture s modulární strukturou. MVC zůstává relevantní pro pochopení evoluce architektur, pro podporu legacy projektů a pro jednoduché obrazovky v UIKit bez složité obchodní logiky.
Často kladené otázky
Hlavním problémem je Massive View Controller. V iOS kontroler UIViewController odpovídá za všechno: zpracování vstupu, aktualizaci View, práci se sítí, navigaci a životní cyklus. V Android Activity/Fragment vykonává analogické funkce. Výsledkem je, že kontroler naroste do tisíců řádků kódu, je obtížné ho testovat a udržovat, čímž porušuje princip jediné odpovědnosti.
V MVC kontroler přímo aktualizuje View a zpracovává uživatelský vstup. V MVVM roli kontroleru plní ViewModel, který nemá referenci na View — data jsou přenášena pomocí mechanismů vázání. MVVM se lépe testuje, protože ViewModel nezávisí na UIKit nebo Android Framework. Apple doporučuje MVVM se SwiftUI, Google — MVVM s Jetpack Compose.
Ano, MVC zůstává fungujícím vzorem pro jednoduché obrazovky a prototypy. Apple doporučuje MVC pro UIKit aplikace s jednoduchými obrazovkami. Pro složité projekty s mnoha obrazovkami, síťovými požadavky a ukládáním do mezipaměti je lepší zvolit MVVM, VIPER nebo Clean Architecture. Začínajícím vývojářům se doporučuje osvojit MVC před studiem složitějších vzorů.
Model se testuje izolovaně — to jsou běžné datové objekty a obchodní logika. Controller je obtížné testovat kvůli závislosti na UIKit nebo Android Framework. Doporučuje se přesouvat obchodní logiku z kontroleru do samostatných služeb nebo interaktorů, které se testují unit testy. View se obvykle netestuje unit testy — pro něj se používají UI testy a snímkové testy.
Na iOS — MVVM se SwiftUI a Combine, standard Apple od roku 2019. Na Android — MVVM s LiveData nebo StateFlow, oficiálně doporučený Google. Pro velké projekty s týmy od 5 vývojářů — Clean Architecture s VIPER na iOS nebo Clean Architecture na Android s rozdělením do modulů podle funkcí. Pro legacy projekty s MVC — postupný refaktoring s přesunem logiky do samostatných služeb.
Shrnutí
Vyvineme mobilní aplikaci na klíč
IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.
Přečtěte si také