Lekce 4 - Jednoduchá kalkulačka pro iOS ve Swift
Minulá lekce, Swift UI pro různé displeje a Autolayout byla stále oddechovější a zkoušeli jsme si
pozicování komponent pomocí Autolayout
.
V dnešním iOS tutoriálu se konečně vrhneme na programování! Prozradím, že půjde o jednoduchou kalkulačku.
Ještě, než začneme se samotnou kalkulačkou, si ukážeme, jak propojit naše UI (tedy jednotlivé komponenty) se Swift kódem, abychom s nimi mohli pracovat a reagovat třeba na stisk tlačítka.
Propojení UI a kódu
Abychom mohli komponenty jakkoliv měnit za běhu aplikace či se dotazovat na jejich stav nebo data, musíme je mít propojené s logikou. Právě teď se nám bude hodit Assistant Editor, který jsme si v úvodní lekci představili.
Nejdříve se ujistěte, že máte otevřený soubor
Main.storyboard
. Přepnutí editorů najdete v pravém horním rohu
- ikonka dvou kruhů přes sebe. Po přepnutí byste měli vidět dvě okna
editoru. V tom prvním a levém zůstal hlavní storyboard a ve druhém máte
otevřený soubor ViewController.swift
. Právě ten je propojený s
naším controllerem. Vše je již v projektu přednastavené, jak přidávat
controllery a tím další obrazovky si ukážeme v následujících lekcích.
Pokud náhodou v pravé části nemáte korektní swift soubor, můžete si ho
manuálně vybrat v navigaci přímo nad editorem. Místo Automatic zvolíte
Manual a proklikáte se k souboru.
Nyní konečně můžeme začít s propojením UI a kódu. Označte
Label
, který jsme na začátku tutoriálu přidali, a za držení
Ctrl klikněte levým tlačítkem a kurzor přesuňte do editoru se
swift souborem. Zobrazí se vám modrá linka a nápis "Insert Outlet or Outlet
Collection". Pusťte tlačítko myši a zobrazí se dialog níže.

Místo Ctrl a levého tlačítka můžete kliknout a táhnout pravým bez držení Ctrl.
V dialogu stačí zadat jméno vaší komponenty, takže např.
myLabel
a kliknout na Connect.

Gratuluji! Právě jste úspěšně propojili komponentu s kódem a váš
Label
je možné upravovat. V controlleru je připravena metoda
viewDidLoad()
, která se zavolá vždy po inicializaci UI
controlleru. Zde můžete vyzkoušet, že s vaším Label
em lze
manipulovat. Například mu změnit text a barvu.
override func viewDidLoad() { super.viewDidLoad() myLabel.text = "Hello from Code!" myLabel.textColor = UIColor.red }
Jakmile propojíme komponentu a v kódu se nám vytvoří
@IBOutlet
, musíme si dát pozor, pokud budeme tuto referenci
někdy mazat (daný řádek kódu). Např. když zjistíme, že
Label
nepotřebujeme měnit a smažeme tento řádek kódu, musíme
také odstranit propojení, které jsme vytvořili. V opačném případě nám
aplikace při načítání controlleru spadne a z chybové hlášky nebude moc
zřejmé, v čem je problém.
Pro smazání propojení stačí pravým kliknout na Label
buď
přímo v UI nebo v seznamu v pravém sloupci a pod Referencing outlets a
odebrat propojení.

Reakce na stisk tlačítka a další události
@IBOutlet
není jedinou možností, jak propojit UI a kód.
Druhou je @IBAction
, která reaguje na akce uživatele. Nejlepší
příklad bude tlačítko, jehož propojení si ukážeme. Přidejme
Button
do našeho controlleru a pokud nemáte otevřený Assistant
Editor, tak ho otevřete. Zkrátka vše stejné jako v případě
Label
u výše.
Jakmile jste tlačítko "přetáhli" do kódu a otevřel se vám Outlet
dialog, tak v první řadě musíte vybrat Action z nabídky Connection. Poté
již stačí jen napsat název (metody, která se vytvoří) a osobně Type
vždy měním z Any
na typ kontrolky, kterou propojuji, v tomto
případě tedy UIButton
. Klikněte na Connect a to je celé. Vaše
nová metoda se provede pokaždé, když dojde ke stisku tlačítka. Osobě
název metod pro tlačítka zakončuji ve stylu Btn_Click
, takže v
ukázkovém případě by mohlo být testBtn_Click
.

Tvorba jednoduché kalkulačky
Abychom si také nové věci vyzkoušeli, vytvoříme velmi primitivní
kalkulačku. Založte si nový Single View App
projekt. Já zvolil
název projektu SimpleCalculator_ITNetwork
.
Návrh UI
Nyní je třeba začít rozmýšlet, co vlastně budeme v naší kalkulačce
potřebovat. Chceme provádět operaci mezi dvěma čísly, což znamená
dvojici Text Field
komponent a také potřebujeme tlačítko
(Button
) pro výpočet.
Také by bylo dobré mít nějakou chytrou volbu pro jednotlivé matematické
operace - sčítání, odečítání, násobení a dělení. Pro to se bude
hodit komponenta PickerView
. Rozmístíme komponenty na
připravený View Controller
, určitě do horní částí, protože
v té spodní bude při zadávání čísel zobrazena klávesnice. Výsledek
bude vypadat zhruba takto:

Pozadí controlleru jsem nastavil na modrou, aby byly zvlášť
TextField
komponenty vidět. Abychom nemuseli nastavovat
constraints pro všechny komponenty, tak využijeme StackView
.
StackView
Díky komponentě StackView
můžete snadno skládat buď za
sebe nebo pod sebe, aniž byste jim museli nastavovat constraints. Zarovnání
(ať už na střed nebo přes constraints) pak nastavíte pouze této
komponentě.
Kromě vlastnosti Axis, která určuje zda se komponenty skládají
vertikálně nebo horizontálně, často využijete Alignment,
Distribution a Spacing. První zarovnává, druhá určuje,
jak se chovají jinak velké komponenty a poslední určuje mezery mezi
komponentami. Ideálně si nyní do StackView
vložte několik
ovládacích prvků a tyto vlastnosti si proklikejte.
Nejjednodušeji komponenty do StackView
"uklidíte"
jejich označením a kliknutím na Embed in v constraints menu, které
jsme již používali. Potom je nutné vybrat Stack View z nabídky. Po
vložení se vám mohou komponenty mírně rozházet, stačí si ale pohrát s
nastavením StackView
. StackView
je také možné
přetáhnout z knihovny komponent (zde jako Vertical Stack View
a
Horizontal Stack View
, orientaci ale můžete změnit) a rovnou si
vybrat orientaci. Takže jdeme komponenty do StackView
uklidit.
Označíme všechny přidané komponenty (pomocí tažení myši nebo třeba
pomocí Cmd + levé tlačítko myši v seznamu nalevo) a v menu, kde
se nastavují constraints, klikneme na tlačítko Embed in a vybereme
Stack View. Tímto vlastně vložíme nový Stack View
a
rovnou nám do něj Xcode vloží označené komponenty, takže nám ušetří
práci. Výsledek je stejný, jako kdybychom Stack View
přetáhli
z knihovny a komponenty do něj manuálně umístili.

Po kliku na Embed in stačí vybrat:

Výsledek:

Pravděpodobně se vám nyní komponenty poněkud rozhází. O nic nejde,
našemu novému StackView
nastavíme constraints 0
od
levého, horního a pravého okraje.
Dále nastavíme constrains našim TextField
komponentám,
můžete je pomocí držení Cmd označit obě. Levou a pravou
constraint nastavíme např. na 10
. Tlačítku nastavíme nějaký
text, např. "Calculate". Já změnil ještě barvu textu na bílou kvůli
modrému pozadí. Našemu Stack View
můžeme nastavit vlastnost
Spacing
, aby komponenty v něm nebyly tak nalepené na sebe.
Uživatelské rozhraní by mělo vypadat zhruba takto:

Zbývá poslední drobnost. Našim TextField
nastavíme v
Attributes inspektoru vlastnost Keyboard Type
na
Number Pad
, vlastnost najdeme v kategorii Text Input Traits. Tímto
se při zadávání rovnou zobrazí klávesnice s čísly.
V Xcode si můžete přepnout náhled pro jednotlivá zařízení a uvidíte, že se naše UI samo přizpůsobuje.

Kód
Tímto naše práce na uživatelském rozhraní končí a přesuneme se do
kódu. Otevřete si v Xcode Assistant editor a vytvoříme outlety pro naše
TextField
komponenty a také pro PickerView
, dále
action pro stiskutí tlačítka.
@IBOutlet weak var firstNumberInput: UITextField! @IBOutlet weak var secondNumberInput: UITextField! @IBOutlet weak var mathOperationPicker: UIPickerView! @IBAction func calculateBtnClick(_ sender: Any) { }
Pro PickerView
nám nebude stačit action, musíme místo toho
nastavit náš controller jako zdroj dat a delegát. K tomu slouží dvojice
protokolů, které přidáme.
class ViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
Potom stačí tyto vlastnosti nastavit v metodě viewDidLoad()
pomocí self
.
override func viewDidLoad() { super.viewDidLoad() mathOperationPicker.dataSource = self mathOperationPicker.delegate = self }
Tímto vlastně PickerView
říkáme, že se náš controller
postará o data a celkově bude komponentu obsluhovat.
Nepůjde nám build, musíme totiž implementovat dvojici metod. Xcode nám je pomůže vygenerovat:
func numberOfComponents(in pickerView: UIPickerView) -> Int { return 1 } func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { return 4 }
Protože víme, kolik komponent a řádků budeme mít, můžeme klidně
"natvrdo" doplnit počty. Zbývá poslední metoda, která není povinná pro
funkční build. Nastavíme, co se vlastně v PickerView
má
zobrazovat.
let mathOperations = ["+", "-", "*", "/"] func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? { return mathOperations[row] }
Aplikaci si můžeme spustit, abychom se přesvědčili, že vše funguje podle očekávání. Design není nejlepší (vlastně je hrozný), ale o ten nám samozřejmě dnes nejde.

Nyní si implementujeme akci tlačítka Calculate pro výpočet.
@IBAction func calculateBtnClick(_ sender: Any) { let firstNumber = Int(firstNumberInput.text!)! let secondNumber = Int(secondNumberInput.text!)! let selectedMathOperation = mathOperationPicker.selectedRow(inComponent: 0) var result : Int switch selectedMathOperation { case 0: result = firstNumber + secondNumber case 1: result = firstNumber - secondNumber case 2: result = firstNumber * secondNumber case 3: result = firstNumber / secondNumber default: result = 0 } displayMessage(message: String(result)) }
A ještě metoda displayMessage()
, která nám zobrazí
výsledek v dialogu s tlačítkem pro zavření. Tento způsob jsem zvolil také
z důvodu, abychom si ukázali jednoduchou tvorbu dialogu.
func displayMessage(message: String) { let alertController = UIAlertController(title: “Result”, message: message, preferredStyle: .alert) alertController.addAction(UIAlertAction(title: “Close”, style: .default, handler: nil)) self.present(alertController, animated: true, completion: nil) }
A můžeme si zkusit něco vypočítat:

Výzva
Jak už jsem zmiňoval na začátku, Autolayout
je komplexní a
pravděpodobně vás bude ze začátku často otravovat. Zároveň vás ale bude
provázet po celou dobu vývoje pro iOS, takže je třeba ho zmáknout.
Ještě než se vrhnete na další lekci, zkuste si vše pořádně
procvičit. Vyberte několik svých oblíbených aplikací a zkusíte
"zkopírovat" jejich UI ve svém projektu. Stačí umístit komponenty na
stejná místa a nastavit constraints. Dole si poté v Xcode změňte
náhledové zařízení a přesvědčte se, že vše funguje jak má -
komponenty jsou na sprvném místě a nevznikají mezery či další problémy.
Komponenty klidně můžete reprezentovat View s různými barvami, jde nám
vyloženě o pozice a správné nastavení Autolayout
.
Ukažte, že to s vývojem pro iOS myslíte vážně a pochlubte se
screenshoty výtvorů níže v komentářích.
V příští lekci, Seznámení se s důležitou komponentou TableView, na nás čeká TableView
.
Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkami
Staženo 81x (60 kB)
Aplikace je včetně zdrojových kódů v jazyce Swift