IT rekvalifikácia. Seniorní programátori zarábajú až 6 000 €/mesiac a rekvalifikácia je prvým krokom. Zisti, ako na to!

14. diel - Ošetrovanie chýb vo Swift

V predchádzajúcom cvičení, Riešené úlohy k 10.-13. lekciu OOP vo Swift, sme si precvičili získané skúsenosti z predchádzajúcich lekcií.

V minulej lekcii, Riešené úlohy k 10.-13. lekciu OOP vo Swift , sme sa zaoberali preťažovaním operátorov a ukázali sme si niekoľko ďalších vychytávok Swiftu. V dnešnom Swift tutoriálu si vysvetlíme poslednú dôležitú tému, než prejdeme na formulárové aplikácie. Touto témou sú chyby. Keďže je vo formulárových aplikáciách budeme stretávať, naučíme sa je dnes ošetrovať.

Chyby

Pri programovaní sa pravidelne objavujú chyby, ako ste si už určite stihli všimnúť :) Niektoré vzniknú našej chybou, proti vzniku iným sa môžeme len ťažko brániť. Typickým príkladom môže byť čítanie dát zo súboru alebo napríklad webové služby, ktorá zrovna nemusí byť dostupná (pretože iný programátor urobil chybu), nefunguje internet a tak podobne.

V tomto tutoriále si ukážeme, ako sa s problémami za behu programu vysporiadať tak, aby celý nespadol.

Swift podobne ako ďalšie moderné jazyky, používa koncept tzv. Výnimiek, ktoré označujú chybový stav aplikácie. Ak prechádzate z iného jazyka, bude vám povedomý, len sa tu termín výnimka nepoužíva a niekoľko vecí funguje trochu inak.

Spustenie nebezpečného kódu

Najskôr si ukážeme, ako sa zachovať, keď nejaký kód môže chybu vyvolať. Swift je v tomto smere prísnejší a funkcie, ktoré môžu vyvolať chybu, musia byť označené kľúčovým slovom throws, ktoré sa píše pred návratový typ. Podobné pravidlo funguje napr. Aj v Jave. S takou funkciou potom nemôžeme pracovať tak, ako sme zvyknutí.

Ukážeme si jednoduchý príklad so zápisom do súboru. Založte si nový Command Line Tool projekt s názvom ChybaSoubor a do main.swift vložte nasledujúci kód:

// Tento kód zatím nefunguje
let dokumentyUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] as NSURL
let souborUrl = dokumentyUrl.appendingPathComponent("info.txt")!
"ITnetwork.cz je fajn web".write(to: souborUrl, atomically: true, encoding: String.Encoding.unicode)

Kód vyššie možno vyzerá hrozivo, ale o nič zložité nejde. Poďme si ho popísať.

  • Prvý riadok získa od systému cestu k priečinku Dokumenty
  • Druhý k ceste pripojí názov súboru, do ktorého budeme zapisovať.
  • Na treťom riadku využijeme metódu na String u pre zápis do súboru. Zvyšné parametre rieši zamknutie súboru a kódovanie češtiny.

Tento kód nám zatiaľ ale nebude fungovať. Je to preto, že môže vyvolať chybu keď do súboru nepôjde zapísať a my sme túto chybu nijako neošetrili. Mechanizmus chýb je vo Swift podobný mechanizmu Optionals, kde sme tiež museli riešiť všetky neočakávané stavy. Metóda write() je v našom prípade označená kľúčovým slovom throws, čo znamená, že akonáhle ju použijeme, musíme sa postarať o možnej chybové stavy.

Try

Problém vyriešime pomocou kľúčového slova try, ktoré napíšeme na začiatok tretieho riadku. Samotné ale nestačí.

Najjednoduchšie je napísať try?, Čo je opäť veľmi podobné Optional konceptu. Ak sa niečo nepodarí, tak sa proste nič nestane a program pokračuje ďalej. Keby sme try? použili s metódou, ktorá vracia hodnotu, tak získame Optional, ktorý bude v prípade chyby prázdny.

Použiť môžeme tiež try!. Tu opäť výkričník značí nebezpečnú situáciu a prakticky Swiftu hovoríme, že k chybe jednoducho nemôže dôjsť a preto nechceme riešiť možné chybové stavy. Ak chyba dôjde, tak náš program spadne.

Do-catch blok

Asi najčastejšou je doplnenie try o blok do-catch. Pozri zápisnicu nižšie:

do
{
    try "ITnetwork.cz je fajn web".write(to: souborUrl, atomically: true, encoding: String.Encoding.unicode)
}
catch {
    print("Do souboru se nepovedlo zapsat")
}

Blok do nám dovolí použiť samotné slovo try. Ak sa vyskytne chyba, vykoná sa blok catch. Tu máme tiež k dispozícii premennú error, z ktorej môžeme získať konkrétne chybu, ak sa niečo pokazí. Z chyby potom môžeme získať dodatočné informácie. V ďalších lekciách si ukážeme, ako pomocou viac catch blokov reagovať na rôzne druhy chýb. Po vykonaní kódu vyššie nájdete vo svojej zložke Dokumenty nový súbor s textom, ktorý sme zapísali.

Blok defer

Blok defer slúži na vykonanie kódu, ktorý sa má uskutočniť po ukončení bloku, v ktorom je try vložené. To znamená v prípade, že sa try podarilo, ale aj v prípade, že nám program skončil v catch bloku pod.

Ešte než si ukážeme ako sa tento blok používa, vytvoríme z nášho skoršieho kódu metódu. Môžeme ju nechať v súbore main.swift. Takéto metóde sa potom hovorí funkcie, pretože metóda patrí vždy do nejakej triedy.

func zapisDoSouboru(text: String) {

    let dokumentyUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] as NSURL
    let souborUrl = dokumentyUrl.appendingPathComponent("info.txt")!

    do {
        try text.write(to: souborUrl, atomically: true, encoding: String.Encoding.unicode)
    }
    catch {
        print("Do souboru se nepovedlo zapsat, protože: \(error)")
    }
}

Aby sme nevymýšľali zbytočne zložitú ukážku, tak si napíšeme jednoduché logovanie zavolanie našej metódy. Doplníme jej začiatok o defer blok:

func zapisDoSouboru(text: String) {
    defer {
        print("Provedena metoda zapisDoSouboru()")
    }
    let dokumentyUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] as NSURL
    let souborUrl = dokumentyUrl.appendingPathComponent("info.txt")!

    do
    {
        try text.write(to: souborUrl, atomically: true, encoding: String.Encoding.unicode)
    }
    catch {
        print("Do soubor se nepovedlo zapsat, protože: \(error)")
    }
    // Zde dojde k vykonání defer bloku
}

Hoci blok defer uvádzame ako prvý, tak sa vykoná akonáhle program opustí scope metódy (blok zložených zátvoriek), v ktorom je defer použité. V našom prípade teda keď sa metóda ukončí. Tento blok sa vykoná vždy, teda keď metóda skončí doběhnutím do jej konca, aj keď skončí tým, že niečo vráti return. Môžeme ho používať aj napr. V cykle, kedy sa spustí po vyskočenie z cyklu pomocou break alebo po jeho prirodzenom dobehnutí a podobne. Skrátka sa nemôže stať, že by sa daný kód nevyvolal. Od toho defer, čo znamená odložiť na neskôr. Typicky sa do tohto bloku umiestňujú tzv. Upratovacie práce ako vyčistenie pamäte a podobne, ktoré sa majú vykonať bez ohľadu na to, či sa nebezpečná operácia podarila alebo nie. S týmto mechanizmom sa ešte stretneme v pokročilejších kurzoch.

Teraz už vieme ako používať cudzie funkcie, ktoré môžu vyvolať chybový stav. Aj keď budeme oveľa častejšie takto spracovávať "cudzie" chyby, naučíme sa aj vyvolávať vlastné. To nás ale čaká zas nabudúce, v lekcii Enum a vlastné ERROR vo Swift .


 

Predchádzajúci článok
Riešené úlohy k 10.-13. lekciu OOP vo Swift
Všetky články v sekcii
Objektovo orientované programovanie vo Swift
Preskočiť článok
(neodporúčame)
Enum a vlastné ERROR vo Swift
Článok pre vás napísal Filip Němeček
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
Autor se věnuje vývoji iOS aplikací (občas macOS)
Aktivity