Tworzenie interfejsu. Dlaczego SwiftUI?
- Przejdź do artykułów z tagiem #app
- Przejdź do artykułów z tagiem #swiftUI
- Przejdź do artykułów z tagiem #UIKit
- Przejdź do artykułów z tagiem A11Y
- Przejdź do artykułów z tagiem accessibility
- Przejdź do artykułów z tagiem accessibilityMatters
- Przejdź do artykułów z tagiem blind
- Przejdź do artykułów z tagiem dostępność
- Przejdź do artykułów z tagiem dostępność cyfrowa
- Przejdź do artykułów z tagiem mobile
- Przejdź do artykułów z tagiem WCAG
- Przejdź do artykułów z tagiem Web Content Accessibility Guidelines
Treść artykułu
W poprzednim artykule dzieliłam się przemyśleniami na temat estetyki komponentów interfejsu użytkownika. Czas więc poukładać je na ekranie. Zadanie wymaga sporo wyobraźni, bo jako osoba niewidoma nie zerknę sobie na makietę i nie przerysuję wymiarów z Figmy. Co więc mogę zrobić?
Alternatywy
Do wyboru mam zasadniczo trzy opcje:
- Mogę użyć frameworka SwiftUI i rozpisać sobie każdy komponent za pomocą prostego kodu.
- Mogę poukładać każdy ekran z komponentów w pliku .storyboard i przypiąć w odpowiedni sposób.
- Mogę wykorzystać elementy UIKit i cały interfejs rozpisać w kodzie.
Zaczynam od SwiftUI
Gdy chcę coś szybko naszkicować, żeby dowiedzieć się, jak się będzie zachowywać na ekranie, moim pierwszym wyborem od momentu pojawienia się jest framework SwiftUI. Jego największymi zaletami są prostota i wieloplatformowość. Tego samego kodu w większości przypadków mogę użyć dla iOS, MacOS, TVOS czy WatchOS.
Co upraszcza mi pracę?
Jest kilka kluczowych aspektów, które sprawiają, że nowe pomysły najszybciej realizuję w SwiftUI. Należą do nich:
- Modułowość. Framework zaprojektowano w taki sposób, że zachęca do tworzenia większych całości z niedużych komponentów, które łatwo jest przenieść z projektu do projektu. Skraca to czas kodowania i redukuje powtarzalność.
- Głównym źródłem wiedzy o zawartości komponentu jest kod. Oznacza to, że nawet jeśli zmodyfikuję jakiś element na kanwie podglądu, zmiany natychmiast widoczne są w dostępnym zaraz obok kodzie źródłowym. Gdy więc zmienię zamysł, wystarczy usunąć kilka linijek, by wycofać zmianę.
- Opisywane powyżej podejście ułatwia odkrywanie nowych funkcjonalności, co wpływa pozytywnie na szybkość uczenia się frameworka. Pozwala też być w miarę na bieżąco z zachodzącymi w nim przez ostatnie lata zmianami.
- Kod jest wyraźnie krótszy. Zyskuje więc nie tylko na jakości, ale przede wszystkim na czytelności. To dla mnie jedna z jego największych zalet.
A czy SwiftUI ma wady?
Oczywiście, całkiem sporo. Najbardziej uciążliwą i jak dotąd nierozwiązaną przyjaźnie kwestią są enigmatyczne błędy wskazywane przez kompilator. I pojawiają się czasami w najbardziej nieoczywistych momentach. Najbardziej frustrują, gdy zabraknie mi gdzieś nawiasu lub przecinka, a kompilator ogłasza coś tak dziwnego, że mam ochotę wyrwać sobie włosy z głowy. Osobie widzącej zazwyczaj edytor podświetla nawiasy na odpowiedni kolor. Łatwo więc może się zorientować, którego brakuje. Ja muszę przewertować wszystko znak po znaku, a i tak często zdarza mi się usuwać większy fragment i pisać coś od zera.
Mimo wszystko jednak wolę ten poziom frustracji niż pisanie kilkakrotnie więcej kodu w UIKit czy AppKit dla osiągnięcia tego samego efektu. Przedstawię Wam to na przykładzie. Poniżej wstawiam dwa fragmenty kodu, które dadzą taki sam efekt końcowy.
Załóżmy, że chcę stworzyć przykładową listę owoców. W SwiftUI będzie to taki kod:
``` swift import SwiftUI struct ContentView: View { let fruits = ["Apple", "Banana", "Orange", "Grapes", "Watermelon"] var body: some View { NavigationView { List(fruits, id: \.self) { fruit in Text(fruit) } .navigationTitle("Fruits") } } } ```
Taka sama lista w UIKit będzie wymagała znacznie dłuższego kodu. Oto i on:
``` swift import UIKit class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate { let fruits = ["Apple", "Banana", "Orange", "Grapes", "Watermelon"] let tableView: UITableView = { let tableView = UITableView() tableView.translatesAutoresizingMaskIntoConstraints = false return tableView }() override func viewDidLoad() { super.viewDidLoad() tableView.dataSource = self tableView.delegate = self view.addSubview(tableView) NSLayoutConstraint.activate([ tableView.topAnchor.constraint(equalTo: view.topAnchor), tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor), tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor), tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor) ]) } // MARK: - UITableViewDataSource func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return fruits.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "FruitCell") ?? UITableViewCell(style: .default, reuseIdentifier: "FruitCell") cell.textLabel?.text = fruits[indexPath.row] return cell } // MARK: - UITableViewDelegate func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { // Handle row selection if needed } } ```
Mój przykład zawiera jedynie prostą listę, a już kod UIKit jest około 3 razy dłuższy. A dobrze wiemy, że przy bardziej złożonych ekranach interfejsu użytkownika zagadnienie znacznie się komplikuje. Tym bardziej, im więcej trzeba ich rozmieścić na ekranie.
Oczywiście w XCode można na pokrętle VoiceOver wybrać nawigację w kodzie po metodach i funkcjach, czy błędach lub ostrzeżeniach, ale przy dłuższych metodach albo ich dużej liczbie, to nadal wymaga sporej koncentracji i przede wszystkim czasu. Czytnik ekranu zapozna mnie z tym samym kodem znacznie wolniej niż przyswajają go Wasze oczy.
Współpraca
Gdy potrzebuję szkicu konkretnego interfejsu, nie skorzystam z Figmy. Ale istnieją alternatywy dość wygodne w użyciu i dla projektanta, i dla mnie. Na rynku dostępne są na przykład aplikacje, które pomagają wygenerować kod SwiftUI z graficznego projektu. Rozwiązania te nie są stuprocentowo skuteczne i często prowadzą do generowania pewnej ilości nadmiernego kodu, który trzeba potem przerobić i oczyścić, ale zrozumienie, czego oczekuje projektant, jest dużo prostsze.
Do dyspozycji mam też zawsze kanwę z podglądem, więc pewne aspekty, które trzeba przedyskutować, daje się szybko pokazać. Dodatkowo mogę też na przykład wygenerować na symulatorze zrzut ekranu i przesłać projektantowi z pytaniem, czy o to mu mniej więcej chodziło.
Podsumowanie
Nie upieram się przy stosowaniu jednego frameworka, bo tworzenie interfejsu aplikacji wymaga połączenia wielu aspektów, by zapewnić użytkownikom najlepsze możliwe doświadczenia. W najbliższej przyszłości zamierzam też pokazać Wam, jak przy pomocy VoiceOver pracować z plikami .storyboard, jednak z racji czytelności i prostoty, SwiftUI pozostanie na razie moim faworytem.
Barbara Filipowska
Audytor dostępności
Polecane artykuły
-
27.09.2024Akademia WCAG
WCAG 2.1. – 4.1.2. Nazwa, rola, wartość (Poziom A) cz. 2
Ostatnio mówiliśmy sobie o różnicy między linkami i przyciskami oraz stanach przycisków. Waszą propozycją w komentarzach było porównanie wizualne linku…
-
13.10.2023Akademia WCAG
WCAG 2.1. – kryterium 2.2.4 – Przerywanie (poziom AAA)
Kolejne kryterium 2.2.4 – przerywanie na poziom AAA WCAG 2.1. Nikt z nas nie lubi, kiedy mu się przerywa, prawda?…
-
21.08.2023Dostępność cyfrowa
Opis alternatywny grafik w technologiach iOS Swift i React
Witajcie, kochani czytelnicy! Dziś chcę poruszyć temat, który być może nie jest codziennie omawiany, ale ma ogromne znaczenie dla wielu…