3. diel - Dokončenie jednoduché kalkulačky pre MacOS vo Swift
V predchádzajúcej lekcii, Návrh jednoduchej kalkulačky pre MacOS , sme dokončili užívateľské rozhranie našej jednoduché kalkulačky a zostáva ho uviesť k životu. To znamená, že dnes začneme písať Swift kód. Ešte predtým ale musíme naše komponenty používateľského rozhrania "napojiť" na kód, aby sme k nim mohli pristupovať.
Budeme totiž potrebovať čítať zadané čísla, vybranú operáciu a
tiež reagovať na stlačenie tlačidla. No a samozrejme nesmieme zabudnúť na
náš Label
, ktorý zobrazí výsledok.
Prepojenie UI s kódom
Prepojenie komponentov s kódom funguje na MacOS úplne rovnako ako na iOS, takže pre mnohých z vás určite pôjde iba o opakovanie.
Začneme otvorením Main.storyboard
a prepneme na Assistant
editor, ktorý zobrazí dva otvorené súbory vedľa seba. Prepínač môžete
vidieť nižšie.
Naľavo by ste mali vidieť naše užívateľské rozhranie a vedľa súbor
ViewController.swift
, ktorý bude obsluhovať práve naše
okno.
Za seba odporúčam označovať komponenty v Document Outline (to je ten zoznam komponentov naľavo od náhľadu používateľského rozhrania). Potom za držanie klávesy Ctrl ťaháme z komponenty do zdrojového súboru, ako je vidieť na animáciu nižšie:
Týmto vytvoríme tzv. @IBOutlet
, čo je špeciálny premenná
odkazujúce na našu komponent. Pri spustení programu bude automaticky
inicializovaná a môžeme pomocou nej čítať obsah Text Field
komponenty a ďalej s ňou manipulovať.
Rovnakým štýlom prepojíme ešte Combo Box
, druhý
Text Field
a posledný Label
pre zobrazenie
výsledku.
V zdrojovom kóde VC by ste mali mať tieto prepojené komponenty:
@IBOutlet var firstInput: NSTextField! @IBOutlet var secondInput: NSTextField! @IBOutlet var mathOperationComboBox: NSComboBox! @IBOutlet var resultsLabel: NSTextField!
Moc nepomáha, že v kóde nie sú komponenty
Text Field
a Label
rozlíšené podobne, ako tomu je u
iOS. Ich automatické nastavenie ale vybraním v časti s tvorbou UI zaistí,
že sa budú správať korektne.
Zostáva tlačidlo. S ním nebudeme pracovať ako s @IBOutlet
,
ale zaujíma nás iba situácie, keď na neho používateľ klikne. Pre to
slúži špeciálne metódy označovanej ako @IBAction
a ich
vytvorenie je dosť podobné @IBOutlet
, stačí zmeniť typ pri
vytváraní, pozri opäť animácie nižšie:
A máme hotovú metódu, ktorá bude automaticky spustená pri každom kliknutí na tlačidlo. Práve tu budeme riešiť výpočet a zobrazovať výsledok.
@IBAction func calculateBtnClicked(_ sender: NSButton) {
}
Úpravy storyboard
Ešte, než sa pustíme do implementácie našej výpočtovej metódy,
uľahčíme si prácu pomocou jednoduchej úpravy v
Main.storyboard
. Ako možno viete, náš rodný jazyk používa
čiarku na oddelenie desatinnej časti čísla, ale angličtina a programovacie
jazyky používajú bodku.
Takže jednoducho našim Text Field
komponentom, respektíve ich
formátující časti, nastavíme, aby ignorovala lokalizáciu. To v preklade
znamená, že bude vždy očakávať bodky v desatinných číslach. Inak nám
nedovolí potvrdiť vstup, rovnako ako keby sme napísali písmeno.
V Document Outline je najskôr potrebné rozkliknúť Text Field
komponent a dostať sa až na Number Formatter
, ako môžete
vidieť na screenshote nižšie:
Potom stačí v Attribute inšpektorovi odškrtnúť voľbu "Localizo Format".
Drobný problém je vyriešený a môžeme sa pustiť do implementácie
našej metódy na výpočet. Čo vlastne chceme robiť? V prvom rade potrebujeme
zistiť zadané čísla od užívateľa a potom podľa vybranej operácie v
komponente Combo Box
vykonať výpočet.
Začneme získaním čísel z Text Field
komponentov, vďaka
Number Formatter
by mali byť vždy validný, ale pre istotu
využijeme guard
a skúsime text z oboch komponentov previesť na
čísla. Keď sa to nepodarí, tak skrátka nič ďalšie robiť nebudeme:
guard let firstNumber = Float(firstInput.stringValue), let secondNumber = Float(secondInput.stringValue) else {return}
V tomto kroku už vieme, že máme k dispozícii dve čísla a môžeme
vykonať výpočet. Z Combo Box
možno jednoducho získať index
zvoleného prvku, takže využijeme jednoduchý switch
a rovno
výsledok nastavíme ako stringValue
našej Label
komponente pre zobrazenie výsledku:
switch mathOperationComboBox.indexOfSelectedItem { case 0: resultsLabel.stringValue = "\(firstNumber + secondNumber)" case 1: resultsLabel.stringValue = "\(firstNumber - secondNumber)" case 2: resultsLabel.stringValue = "\(firstNumber / secondNumber)" case 3: resultsLabel.stringValue = "\(firstNumber * secondNumber)" default: resultsLabel.stringValue = "-" }
Teraz môžete aplikáciu zapnúť a bude počítať. Pre istotu si ukážeme kompletnú metódu pre tlačidlo:
@IBAction func calculateBtnClicked(_ sender: NSButton) { guard let firstNumber = Float(firstInput.stringValue), let secondNumber = Float(secondInput.stringValue) else {return} switch mathOperationComboBox.indexOfSelectedItem { case 0: resultsLabel.stringValue = "\(firstNumber + secondNumber)" case 1: resultsLabel.stringValue = "\(firstNumber - secondNumber)" case 2: resultsLabel.stringValue = "\(firstNumber / secondNumber)" case 3: resultsLabel.stringValue = "\(firstNumber * secondNumber)" default: resultsLabel.stringValue = "-" } }
Naša kalkulačka má jeden drobný problém, v Combo Box
nie je
po zapnutí nič vybrané. To môžeme vyriešiť jedným riadkom kódu v
metóde viewDidLoad()
, ktorá je zavolaná po spustení
aplikácie.
Tu jednoducho vyberieme treba prvú operáciu:
override func viewDidLoad() { super.viewDidLoad() mathOperationComboBox.selectItem(at: 0) }
Ak vám vadí, že sa aplikácia pri skúšaní nezavrie pri zatvorení okna,
existuje na to rýchla oprava. Otvorte si AppDelegate.swift
a
pridajte túto metódu. Xcode vám ju prípadne napovie:
func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { return true }
Jej názov jednoznačne vystihuje, o čo vlastne ide. Keď používateľ zavrie posledný okno (v našom prípade jedinej), dôjde tiež k vypnutiu aplikácie.
Dialóg
Možno vás napadlo, čo sa stane, keď sa používateľ pokúsi deliť
0
? Aplikácia prekvapivo nespadne, ale zobrazí výsledok "inf"
ako infinity čiže nekonečno. Keby sme ako dátový typ používali
Int
miesto Float
, tak aplikácia spadne.
Ani jedno nie je ideálne, takže si ukážeme riešenia a rovno tiež, ako zobraziť informačný dialóg užívateľmi.
Pripravíme si metódu, ktorá zobrazí tento dialóg a informuje
užívateľa, že deliť 0
jednoducho nejde:
func showDivisionByZeroAlert() { let alert = NSAlert() alert.messageText = "Even this cool app cannot divide by 0!" alert.runModal() }
Zobrazenie základného dialógu je veľmi jednoduché. Stačí vytvoriť
inštanciu NSAlert
a pridať text. Potom už len stačí dialóg
zobraziť. Bude vyzerať takto:
Zostáva teda vyriešiť situáciu, keď sa používateľ pokúsi deliť
0
. Upravíme teda náš switch
v metóde obsluhujúci
tlačidlo, konkrétne prípad, keď je vybrané delenie. Pred samotnej delenie
umiestnime podmienku, kde sa jednoducho spýtame, či náhodou nie je druhé
číslo 0
. Ak áno, tak zobrazíme dialóg a ďalej
nepokračujeme:
case 2: if secondNumber == 0 { showDivisionByZeroAlert() return } resultsLabel.stringValue = "\(firstNumber / secondNumber)"
A to je celé! Máme prvý funkčný MacOS aplikáciu.
V budúcej lekcii, PRIPOMIENKOVÉ narodenín pre MacOS - Príprava UI , začneme už komplexnejšie projekt, na ktorom sa naučíme používať ďalšie ovládacie prvky.
Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.
Stiahnuť
Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami
Stiahnuté 19x (38.85 kB)
Aplikácia je vrátane zdrojových kódov v jazyku Swift