Do-Catch: wat is het, constructie en foutafhandeling in Swift

Auteur: IT Sectr Gepubliceerd: 2026-05-26 Leestijd: 8 min

Do-Catch — de Swift-taalconstructie voor foutafhandeling die uitzonderingen opvangt die via throw worden gegenereerd en het bijbehorende codeblok uitvoert. In tegenstelling tot traditionele try-catch in andere talen, vereist Swift dat functies die een fout kunnen gooien expliciet worden gemarkeerd met de modifier throws. Volgens Swift.org, 2026 is Do-Catch het primaire mechanisme voor foutafhandeling in Swift, dat typeveiligheid biedt.

Belangrijkste punten

  • Do-Catch — Swift-constructie die fouten opvangt uit blokken met try en throw.
  • throws — functiemarker die aangeeft dat de functie een fout kan gooien.
  • try — sleutelwoord voor het aanroepen van een throwing-functie binnen een do-blok.
  • catch — foutafhandelingsblok met mogelijkheid tot matching op type.
  • try? en try! — alternatieve vormen die de fout omzetten in nil of een crash veroorzaken.

Wat is Do-Catch?

Do-Catch — is een constructie in Swift bestaande uit een do-blok, waarbinnen code wordt uitgevoerd die een fout kan gooien, en een of meer catch-blokken die deze fout afhandelen. Het do-blok bevat aanroepen van throwing-functies gemarkeerd met try, en de catch-blokken matchen de fout op type.

Swift implementeert een model van gestructureerde foutafhandeling, anders dan uitzonderingen in Objective-C. Hier is een fout geen exception met stack-ontwikkeling, maar een waarde die voldoet aan het Error-protocol. Het gooien van een fout via throw draagt controle over aan het dichtstbijzijnde catch-blok zonder overhead van stack-ontwikkeling.

Een belangrijk kenmerk van Swift — explicietheid van afhandeling. De compiler staat niet toe een throwing-functie aan te roepen zonder try, do-catch of een alternatief mechanisme (try?, try!). Dit elimineert situaties waarin een fout onopgemerkt blijft.

Foutmodel in Swift: Error-protocol en throwing-functies

De basis van foutafhandeling in Swift is het Error-protocol. Elk type dat aan dit protocol voldoet, kan via throw worden gegooid. Meestal worden fouten gedefinieerd als een enum met Error-bevestiging.

Error-protocol

Error — een leeg protocol (marker). Het vereist geen implementatie van methoden, alleen bevestiging van conformiteit. De Swift-compiler gebruikt Error voor statische controle: een functie met throws kan alleen een waarde gooien die aan Error voldoet.

Throwing-functies

Een functie gemarkeerd met throws moet worden aangeroepen met try. Als binnen zo'n functie een throw plaatsvindt, wordt controle overgedragen aan de aanroepende do-catch. Als de fout nergens in de aanroepketen wordt afgehandeld, wordt deze doorgegeven aan een hoger niveau.

swift
enum FileError: Error {
    case notFound
    case permissionDenied
    case corrupted(String)
}

func readFile(path: String) throws -> String {
    guard FileManager.default.fileExists(atPath: path) else {
        throw FileError.notFound
    }
    return try String(contentsOfFile: path)
}

Foutpropagatie met rethrows

rethrows — een modifier voor functies die een throwing-closure als parameter accepteren. Als de doorgegeven closure geen fout gooit, kan de rethrows-functie zonder try worden aangeroepen. Dit maakt het mogelijk generieke hogere-orde functies te schrijven die compatibel zijn met throwing en non-throwing closures.

Do-Catch-syntax: meerdere catch-blokken

Swift ondersteunt meerdere catch-blokken met matching op fouttype. Dit lijkt op when in Kotlin of switch op type: de eerste overeenkomende catch wordt uitgevoerd, de rest wordt overgeslagen.

Matching op type

Elk catch-blok kan een matchpatroon bevatten voor een specifiek fouttype. Swift controleert de blokken op volgorde, dus specifiekere typen moeten voor algemenere komen. Als geen patroon overeenkomt, wordt het catch-blok zonder patroon uitgevoerd.

Meerdere typen afhandelen

Typeveiligheid van Do-Catch maakt het mogelijk elke fout afzonderlijk te behandelen of meerdere typen in één blok te combineren via komma's in pattern-matching. Dit elimineert omslachtige if-else-ketens die kenmerkend zijn voor Objective-C, waar foutanalyse gebeurde via retourcode of NSError met controle van domain en code.

Swift ondersteunt ook catch where — matching met een extra voorwaarde. Men kan bijvoorbeeld fouten filteren op specifieke code of tekst: catch URLError where error.code == .notConnectedToInternet. Dit vermindert het aantal catch-blokken terwijl de precisie van afhandeling behouden blijft.

Voor het debuggen van throwing-functies biedt Swift het verschil tussen fouten en uitzonderingen. Een Swift-fout is een geretourneerde waarde die geen stack-ontwikkeling vereist. Objective-C-uitzonderingen (@try/@catch) werken op run-time-niveau en worden alleen gebruikt voor fatale fouten. Do-Catch handelt precies fouten af, niet uitzonderingen, wat het voorspelbaar en performant maakt.

Bij het ontwikkelen van bibliotheken en SDK's is het belangrijk te onthouden dat throwing-functies deel uitmaken van het publieke contract. Het fouttype is niet gespecificeerd in de handtekening, dus documenteer welke fouten de functie kan gooien in een opmerking of via een Result-achtige enum. Dit helpt API-gebruikers correcte catch-blokken te schrijven zonder in de implementatie te kijken.

In de context van asynchroon programmeren lost Do-Catch met async/await het callback hell-probleem op. Voorheen vereiste foutafhandeling in asynchrone Swift-code geneste closures met Error?-controle in de completion handler. Met async/await en Do-Catch ziet asynchrone throwing-code eruit als synchrone code, wat het lezen en onderhouden van complexe aanvraagketens met foutafhandeling bij elke stap vereenvoudigt.

swift
do {
    let content = try readFile(path: "/data/config.json")
    process(content)
} catch FileError.notFound {
    createDefaultConfig()
} catch FileError.permissionDenied {
    requestAccess()
} catch FileError.corrupted(let detail) {
    logCorruption(detail)
} catch {
    print("Onbekende fout: \(error)")
}

Try-varianten: try, try?, try! en wanneer ze te gebruiken

Swift biedt drie varianten voor het aanroepen van throwing-functies: try, try? en try!. Elke variant lost een specifieke taak op en heeft zijn beperkingen.

try — standaard aanroep

try wordt gebruikt binnen een do-blok en de fout wordt afgehandeld in catch. Dit is de primaire manier om throwing-functies aan te roepen. De compiler vereist dat try zich in een context bevindt waar de fout kan worden opgevangen.

try? — conversie naar Optional

try? converteert het resultaat van een throwing-functie naar Optional. Als de functie een fout gooit, retourneert try? nil, anders — Optional met de succeswaarde. Handig voor aanroepen waar de fout kan worden genegeerd, maar een succesindicator nodig is.

try! — geforceerde uitvoering

try! onderdrukt foutafhandeling. Als de throwing-functie een fout gooit, wordt de applicatie beëindigd met een runtime-fout. Gebruik try! alleen wanneer u absoluut zeker bent dat de fout onmogelijk is — bijvoorbeeld bij het laden van een ingebedde resource.

swift
// try? — negeren de fout, krijgen nil bij storing
if let data = try? Data(contentsOf: url) {
    processData(data)
}

// try! — alleen als de fout gegarandeerd onmogelijk is
let bundled = try! String(contentsOfFile: "Assets/default.txt")

// try — standaard optie in do-catch
do {
    let result = try performNetworkRequest()
    updateUI(result)
} catch {
    showError(error)
}

Do-Catch in iOS-ontwikkeling: praktische voorbeelden

Do-Catch wordt actief gebruikt in iOS-ontwikkeling voor het werken met systeem-API's. Laten we typische scenario's bekijken: werken met het bestandssysteem, Core Data en netwerkverzoeken.

Bestandssysteem

Veel methoden van FileManager zijn throwing. Do-Catch maakt het mogelijk ontbrekende bestanden, bezette resources of ontoereikende rechten correct af te handelen.

Netwerkverzoeken met Codable

JSON-parsen via JSONDecoder is een throwing-bewerking. Do-Catch vangt decodeerfouten en netwerkstoringen afzonderlijk op en biedt de gebruiker de exacte fouttekst.

swift
struct User: Codable {
    let id: Int
    let name: String
}

func fetchUser(id: Int) async throws -> User {
    let url = URL(string: "https://api.example.com/users/\(id)")!
    let (data, _) = try await URLSession.shared.data(from: url)
    return try JSONDecoder().decode(User.self, from: data)
}

// Aanroep met afhandeling
do {
    let user = try await fetchUser(id: 42)
    showUser(user)
} catch let error as URLError {
    showNetworkAlert(error)
} catch let error as DecodingError {
    showParseError(error)
} catch {
    showGenericError(error)
}

Veelvoorkomende fouten bij het werken met Do-Catch

Ontwikkelaars, vooral degenen die overstappen van andere talen, maken vaak karakteristieke fouten bij het gebruik van Do-Catch. Laten we de meest voorkomende bekijken.

  • Vergeten try — het aanroepen van een throwing-functie zonder try leidt tot een compilatiefout. Swift staat niet toe fouten impliciet te negeren.
  • Lege catch — een catch-blok zonder afhandeling verbergt de fout. Log of handel de fout altijd af, zelfs als deze onmogelijk lijkt.
  • Catch zonder matching — een enkele algemene catch voor alle fouten ontneemt de voordelen van typeveiligheid. Verdeel de afhandeling per type over meerdere blokken.
  • Overmatig gebruik van try! — try! in productiecode is een bron van onverwachte crashes. Gebruik alleen voor ingebedde resources of tests.

Veelgestelde vragen

Waarin verschilt Do-Catch in Swift van try-catch in andere talen?

In Swift is een fout een waarde die voldoet aan het Error-protocol, geen exception met stack-ontwikkeling. Throwing-functies moeten expliciet worden gemarkeerd met throws en de compiler vereist try bij aanroep — dit elimineert onafgehandelde fouten tijdens compilatie.

Kan Do-Catch worden gebruikt met async/await?

Ja, async-functies kunnen ook throws zijn, en do-catch werkt voor hen. Het aanroepen van een async throwing-functie vereist try await binnen een do-blok. Dit is de standaard manier van foutafhandeling in asynchrone Swift-code.

Hoe handel ik een fout af zonder do-catch?

Er zijn alternatieven: try? converteert de fout naar nil, try! veroorzaakt een crash bij een fout, en rethrows maakt het mogelijk de fout uit een closure door te geven. Do-catch blijft de primaire manier van expliciete afhandeling.

Kan één functie verschillende typen fouten gooien?

Swift typeert gegooiden fouten niet — elke throwing-functie kan elk type gooien dat voldoet aan Error. Verdeel de afhandeling via matching in catch op specifieke fouttypen.

Is het de moeite waard om alle fouten in een eigen type te verpakken?

Ja, dit is de beste praktijk. Definieer AppError als een enum met Error-bevestiging en converteer systeemfouten naar domeinfouten. Dit uniformeert de afhandeling en isoleert de applicatielaag van systeemdetails.

Samenvatting

  • Do-Catch — Swift-constructie voor foutafhandeling met verplichte throws-markering op functies en try bij aanroep.
  • Swift-fouten zijn waarden die voldoen aan het Error-protocol, geen uitzonderingen met stack-ontwikkeling, wat nul overhead geeft bij afwezigheid van storingen.
  • Meerdere catch maken het mogelijk verschillende fouttypen afzonderlijk te behandelen met pattern-matching analoog aan switch.
  • try? converteert de fout naar nil voor eenvoudige scenario's, try! — geforceerde aanroep met crashrisico, alleen gebruikt voor gegarandeerd succesvolle operaties.
  • Do-Catch met async/await — de standaard manier van foutafhandeling in asynchrone Swift-code met try await.
  • Vermijd lege catch en overmatig gebruik van try! — dit verbergt fouten en leidt tot onverwachte storingen in productie.

We ontwikkelen een mobiele applicatie turnkey

IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.

Bespreek het project

Lees ook