UIKit — to framework do budowania graficznych interfejsów w aplikacjach na iOS i macOS. Zestaw zawiera UIView, UIViewController, elementy sterowania oraz system Auto Layout, umożliwiając tworzenie adaptacyjnych i interaktywnych ekranów. Według Apple Developer Documentation (2025), UIKit zawiera ponad 200 klas do pracy z oknami, widokami, animacjami, gestami i tekstem — to podstawa wszystkich aplikacji na iPhone i iPad.
Najważniejsze
UIKit — to framework od Apple, dostarczający klasy do tworzenia i zarządzania interfejsem użytkownika na iOS, iPadOS i macOS (poprzez Mac Catalyst). Działa na bazie Core Animation, Core Graphics i Quartz Core, abstrahując niskopoziomowe renderowanie do wysokopoziomowych obiektów — przycisków, etykiet, obrazów i kontenerów. UIKit pojawił się wraz z iPhone OS 1 w 2007 roku i pozostaje głównym frameworkiem do tworzenia aplikacji na iOS obok SwiftUI.
Framework stosuje podejście imperatywne: programista tworzy instancje klas UIButton, UILabel, UIImageView, ustawia ich właściwości (kolor, czcionkę, położenie) i dodaje do hierarchii widoków przez addSubview. Każda zmiana interfejsu jest wykonywana jawnie — żadnej magii aktualizacji w tle. To odróżnia UIKit od deklaratywnych frameworków takich jak SwiftUI, gdzie opis stanu automatycznie przerysowuje interfejs.
Framework zawiera kilka kategorii klas. UIView — podstawowy element, od którego dziedziczą wszystkie komponenty wizualne. UIWindow — kontener najwyższego poziomu, przez który widoki są wyświetlane na ekranie. UIViewController — kontroler zarządzający zestawem widoków i reagujący na obroty ekranu, pojawienie się klawiatury oraz systemowe powiadomienia. UIApplication — punkt wejścia, przetwarzający zdarzenia dotyku i naciśnięcia przycisków.
Do tekstu używane są UILabel (statyczny tekst), UITextField (jednowierszowe wprowadzanie), UITextView (wielowierszowe wprowadzanie). Do przycisków — UIButton, w tym systemowe, niestandardowe i z ikonografią SF Symbols. Do nawigacji — UINavigationController, UITabBarController i UISplitViewController. W sumie UIKit zawiera ponad 200 publicznych klas.
Architektura UIKit opiera się na warstwach: każda warstwa odpowiada za swój aspekt wyświetlania. Na najniższym poziomie znajduje się Core Graphics — silnik renderowania ścieżek, tekstu i obrazów. Wyżej — Core Animation, zarządzająca kompozycją warstw (CALayer) i animacjami między stanami. UIKit nadbudowuje na nich obiektowo zorientowane API: UIView, UIViewController i UIResponder.
Każda aplikacja ma hierarchię widoków (view hierarchy) — drzewo, którego korzeniem jest UIWindow. Pod nim — główny UIViewController, jego widok, a wewnątrz — zagnieżdżone subviews. Zdarzenia dotyku rozprzestrzeniają się w łańcuchu responder chain: od najbardziej zagnieżdżonego widoku do rodziców i dalej do UIApplication. Jeśli żaden obiekt nie przetworzył dotyku, jest ignorowany.
Każdy UIView zawiera warstwę CALayer, odpowiedzialną za renderowanie pikseli na ekranie. Widok zarządza dotykami i accessibility, warstwa — grafiką: shadow, cornerRadius, border, transform. Podział pozwala przenieść ciężką grafikę na osobny wątek (render server), nie blokując main thread. Apple zaleca pracę bezpośrednio z CALayer, jeśli potrzeba więcej niż 200 widoków na ekranie — zmniejsza to obciążenie CPU.
Łańcuch responder zaczyna się od obiektu, który pierwszy otrzymuje zdarzenie dotyku. Jeśli nie przetwarza zdarzenia (metoda touchesBegan nie jest nadpisana), zdarzenie jest przekazywane do następnego respondera w łańcuchu: next, superview, next responder, UIViewController, UIWindow, UIApplication, App Delegate. Pozwala to przechwytywać globalne gesty i zdarzenia klawiatury na poziomie sceny, bez dodawania obsługi do każdego widoku.
Każdy UIViewController przechodzi przez ściśle określoną sekwencję zdarzeń. Cykl życia obejmuje fazy: inicjalizacja, załadowanie widoku, pojawienie się na ekranie, aktualizacja układu przy obrocie, ukrycie, opuszczenie ekranu i zwolnienie pamięci. Programista nadpisuje odpowiednie metody, aby wykonać swój kod na każdym etapie.
class ProfileViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
setupUI()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
loadUserProfile()
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
clearCache()
}
}
W viewDidLoad konfiguruje się interfejs — tworzy subview, ustawia ograniczenia, subskrybuje delegatów. W viewWillAppear wykonuje się operacje przed wyświetleniem: ładowanie świeżych danych z sieci, aktualizacja wartości. viewDidDisappear — miejsce do wypisania się z powiadomień i czyszczenia tymczasowych danych. Wywołanie super jest obowiązkowe we wszystkich nadpisaniach, w przeciwnym razie łańcuch zdarzeń zostanie przerwany.
W starszych wersjach iOS istniała metoda viewDidUnload, wywoływana przy braku pamięci. Od iOS 6 metoda została usunięta — teraz UIKit automatycznie zwalnia widoki kontrolera, gdy nie są widoczne. Programista musi jedynie ustawić wszystkie referencje do widoków jako weak, aby ARC poprawnie zwolnił pamięć po otrzymaniu ostrzeżenia od systemu.
UIKit obsługuje dwa typy przejść: segue (przez Storyboard) i programowa nawigacja przez UINavigationController. Programowe przejście wygląda tak: navigationController?.pushViewController(detailVC, animated: true). Przy tym cykl życia detailVC przebiega normalnie — viewDidLoad wywoływane jest raz, viewWillAppear — za każdym razem przy wyświetleniu.
Auto Layout — to system pozycjonowania elementów oparty na matematycznych relacjach (ograniczeniach). Zamiast sztywno określonych współrzędnych X i Y programista opisuje reguły: „przycisk znajduje się po prawej stronie etykiety z odstępem 16pt” lub „widok rozciąga się na szerokość ekranu z odstępami 20pt z lewej i prawej strony”. System rozwiązuje powstały układ równań w runtime, dostosowując interfejs do dowolnego rozmiaru ekranu.
Ograniczenia można ustawić w Interface Builder (przez drag-and-drop) lub programowo w Swift. Każde ograniczenie to instancja klasy NSLayoutConstraint z parametrami: firstItem, firstAttribute, relation, secondItem, secondAttribute, multiplier, constant. Ograniczenia aktywuje się przez isActive = true lub masowo przez NSLayoutConstraint.activate().
Wraz z iPhone X (2017) Apple wprowadziło Safe Area — obszar ekranu wolny od notch, zaokrąglonych rogów i wskaźnika home bar. Ograniczenia powinny być przypisywane do view.safeAreaLayoutGuide, a nie do view. Layout Margins dodają wewnętrzne odstępy widoku, domyślnie 8pt lub 16pt w zależności od kontekstu. Użycie safeAreaLayoutGuide gwarantuje poprawne wyświetlanie na wszystkich generacjach iPhone i iPad.
Auto Layout obsługuje animację poprzez zmianę stałych ograniczeń. Wystarczy zaktualizować constant ograniczenia i wywołać UIView.animate z layoutIfNeeded wewnątrz bloku animacji. System płynnie przelicza położenie wszystkich widoków w hierarchii. Ta technika jest używana do rozwijanych bloków, adaptacyjnego panelu klawiatury i zmiany orientacji ekranu.
UITableView i UICollectionView — dwa potężne narzędzia UIKit do wyświetlania list i siatek. UITableView nadaje się do pionowych list z jedną kolumną (czat, ustawienia, kanał wiadomości). UICollectionView — do siatek, poziomych list, karuzel i niestandardowych układów (galeria, produkty, kalendarz). Obie klasy używają wzorca delegacji do oddzielenia danych od wyglądu.
Źródłem danych jest protokół UITableViewDataSource z obowiązkowymi metodami numberOfRowsInSection i cellForRowAt. Delegat UITableViewDelegate obsługuje naciśnięcia na komórki, wysokość wierszy i zdarzenia przewijania. Mechanizm reuse identifier ponownie wykorzystuje komórki, które zniknęły poza ekranem, co jest krytyczne dla wydajności na dużych listach.
class ContactsViewController: UITableViewController {
private let contacts = ["Anna", "Borys", "Wiktor"]
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(UITableViewCell.self,
forCellReuseIdentifier: "cell")
}
override func tableView(_ tableView: UITableView,
numberOfRowsInSection section: Int) -> Int {
return contacts.count
}
override func tableView(_ tableView: UITableView,
cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell",
for: indexPath)
var content = cell.defaultContentConfiguration()
content.text = contacts[indexPath.row]
cell.contentConfiguration = content
return cell
}
}
Przykład pokazuje minimalny kontroler do wyświetlania tablicy ciągów znaków. Komórka jest konfigurowana przez UIListContentConfiguration — nowoczesne API (iOS 14+), które zastąpiło przestarzałe textLabel i detailTextLabel. Rejestracja klasy komórki w viewDidLoad jest obowiązkowa, w przeciwnym razie aplikacja padnie z wyjątkiem w runtime.
Od iOS 13 Apple zaleca UICollectionViewCompositionalLayout do budowania złożonych układów. Programista opisuje sekcję, grupę, element i ich rozmiary deklaratywnie — otrzymuje siatkę o dowolnej geometrii: pasek, siatka 2x2, karuzela, ornament. Compositional Layout zastąpił przestarzały UICollectionViewFlowLayout we wszystkich nowych projektach. W połączeniu z DiffableDataSource aktualizacja kolekcji sprowadza się do jednego wywołania apply(snapshot), a animacja zmian jest wykonywana automatycznie.
Poniżej znajdują się dwa praktyczne przykłady użycia UIKit w rzeczywistych zadaniach: tworzenie niestandardowego widoku z cieniem i zaokrągleniem oraz obsługa gestu przesunięcia do usuwania elementu z listy.
extension UIView {
func applyCardStyle() {
layer.cornerRadius = 12
layer.shadowOpacity = 0.15
layer.shadowRadius = 8
layer.shadowOffset = CGSize(width: 0, height: 2)
layer.masksToBounds = false
}
}
@objc private func handleSwipe(_ gesture: UISwipeGestureRecognizer) {
guard let swipedView = gesture.view else { return }
UIView.animate(withDuration: 0.3) {
swipedView.alpha = 0
swipedView.transform = CGAffineTransform(translationX: 300, y: 0)
} completion: { _ in
swipedView.removeFromSuperview()
}
}
Rozszerzenie applyCardStyle dodaje cień i zaokrąglenie dowolnemu widokowi — przydatne do kart produktów, profili i powiadomień. Metoda handleSwipe z animacją usuwa element, jeśli użytkownik przesunął go w prawo. Obsługa dodawana jest do widoku przez addGestureRecognizer z konfiguracją UISwipeGestureRecognizer(direction: .right). Ustawienie masksToBounds = false jest ważne, aby cień nie został przycięty przez granice widoku.
Do bardziej złożonych interfejsów używaj UIStackView — kontenera, który automatycznie rozmieszcza zagnieżdżone widoki poziomo lub pionowo. Stack View upraszcza układ: nie trzeba ustawiać ograniczeń dla każdego elementu, wystarczy jedno ograniczenie dla samego stosu.
Często zadawane pytania
Frame — prostokąt we współrzędnych superview (pozycja + rozmiar). Bounds — prostokąt we własnych współrzędnych widoku (zawsze zaczyna się od 0,0). Frame zmienia się przy rotate i scale, bounds — nie.
UIKit automatycznie zwalnia widoki ukrytych kontrolerów. Programista musi jedynie deklarować właściwości widoków jako weak var, aby ARC mógł zwolnić pamięć po ostrzeżeniu systemu.
W nowych projektach Apple zaleca SwiftUI. Jeśli projekt jest w UIKit — używaj XIB dla poszczególnych ekranów lub programowego układu przez SnapKit. Storyboard tworzy merge conflicts i spowalnia budowanie.
Użyj UIColor z obsługą traitCollection: UIColor { $0.userInterfaceStyle == .dark ? ... : ... }. Aktywuj Dark Mode w Info.plist kluczem UIUserInterfaceStyle.
UIStackView automatycznie oblicza pozycje i rozmiary zagnieżdżonych widoków na podstawie alignment, distribution i spacing. Skraca to kod ograniczeń o 60–80% i upraszcza adaptację do różnych ekranów.
Podsumowanie
Opracujemy aplikację mobilną pod klucz
IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.
Przeczytaj również