Do-Catch: vad är det, konstruktion och felhantering i Swift

Författare: IT Sectr Publicerad: 2026-05-26 Lästid: 8 min

Do-Catch — Swift-språkets konstruktion för felhantering som fångar undantag som kastas via throw och utför motsvarande kodblock. Till skillnad från traditionell try-catch i andra språk kräver Swift explicit markering av funktioner som kan kasta ett fel med modifieraren throws. Enligt Swift.org, 2026 är Do-Catch den primära mekanismen för felhantering i Swift, som säkerställer säkerhet på typnivå.

Huvudpunkter

  • Do-Catch — Swift-konstruktion som fångar fel från block med try och throw.
  • throws — funktionsmarkör som signalerar att funktionen kan kasta ett fel.
  • try — nyckelord för att anropa en throwing-funktion inuti ett do-block.
  • catch — felhanteringsblock med möjlighet till matchning efter typ.
  • try? och try! — alternativa former som omvandlar felet till nil eller orsakar en crash.

Vad är Do-Catch?

Do-Catch — är en konstruktion i Swift som består av ett do-block, inom vilket kod som kan kasta ett fel körs, och ett eller flera catch-block som hanterar detta fel. Do-blocket innehåller anrop till throwing-funktioner markerade med try, och catch-blocken matchar felet efter typ.

Swift implementerar modellen strukturerad felhantering, som skiljer sig från undantag i Objective-C. Här är ett fel inte ett exception med stackavveckling, utan ett värde som motsvarar protokollet Error. Att kasta ett fel via throw överför kontrollen till närmaste catch-block utan kostnad för stackavveckling.

En nyckelfunktion i Swift — explicit hantering. Kompilatorn tillåter inte anrop av en throwing-funktion utan try, do-catch eller alternativ mekanism (try?, try!). Detta eliminerar situationer där ett fel förblir oupptäckt.

Felmodell i Swift: Error-protokollet och throwing-funktioner

Grunden för felhantering i Swift är protokollet Error. Alla typer som motsvarar detta protokoll kan kastas via throw. Vanligtvis definieras fel som en enum med Error-bekräftelse.

Error-protokollet

Error — ett tomt protokoll (markör). Det kräver inte implementering av metoder, endast bekräftelse av överensstämmelse. Swift-kompilatorn använder Error för statisk kontroll: en funktion med throws kan bara kasta ett värde som motsvarar Error.

Throwing-funktioner

En funktion markerad med throws måste anropas med try. Om en throw inträffar inuti en sådan funktion överförs kontrollen till den anropande do-catch. Om felet inte hanteras någonstans i anropskedjan propageras det till en högre nivå.

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)
}

Felpropagering med rethrows

rethrows — en modifierare för funktioner som tar en throwing-closure som parameter. Om den skickade closure inte kastar ett fel kan rethrows-funktionen anropas utan try. Detta gör det möjligt att skriva generiska högre ordningens funktioner som är kompatibla med throwing och non-throwing closures.

Do-Catch-syntax: flera catch-block

Swift stöder flera catch-block med matchning efter feltyp. Detta liknar when i Kotlin eller switch efter typ: den första matchande catch körs, resten hoppas över.

Matchning efter typ

Varje catch-block kan innehålla ett matchmönster för en specifik feltyp. Swift kontrollerar blocken i ordning, så mer specifika typer bör placeras före allmänna. Om inget mönster matchar körs catch-blocket utan mönster.

Hantera flera typer

Typsäkerhet Do-Catch gör det möjligt att hantera varje fel separat eller kombinera flera typer i ett block via kommatecken i pattern-matching. Detta eliminerar omfattande if-else-kedjor som är karakteristiska för Objective-C, där felanalys gjordes via returkod eller NSError med kontroll av domain och code.

Swift stöder också catch where — matchning med ett extra villkor. Man kan till exempel filtrera fel efter specifik kod eller text: catch URLError where error.code == .notConnectedToInternet. Detta minskar antalet catch-block samtidigt som precisionen i hanteringen bibehålls.

För felsökning av throwing-funktioner tillhandahåller Swift skillnaden mellan fel och undantag. Ett Swift-fel är ett returnerat värde som inte kräver stackavveckling. Objective-C-undantag (@try/@catch) fungerar på runtime-nivå och används endast för allvarliga fel. Do-Catch hanterar just fel, inte undantag, vilket gör det förutsägbart och prestandaeffektivt.

Vid utveckling av bibliotek och SDK är det viktigt att komma ihåg att throwing-funktioner är en del av det offentliga kontraktet. Feltypen specificeras inte i signaturen, så dokumentera vilka fel funktionen kan kasta i en kommentar eller via en Result-liknande enum. Detta hjälper API-användare att skriva korrekta catch-block utan att behöva titta på implementeringen.

I sammanhanget av asynkron programmering löser Do-Catch med async/await callback hell-problemet. Tidigare i Swift krävde felhantering i asynkron kod kapslade closures med Error?-kontroll i completion handler. Med async/await och Do-Catch ser asynkron throwing-kod ut som synkron kod, vilket förenklar läsning och underhåll av komplexa kedjor med felhantering vid varje steg.

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("Okänt fel: \(error)")
}

Try-varianter: try, try?, try! och när de ska användas

Swift erbjuder tre varianter för att anropa throwing-funktioner: try, try? och try!. Varje variant löser en specifik uppgift och har sina begränsningar.

try — standardanrop

try används inuti ett do-block och felet hanteras i catch. Detta är det primära sättet att anropa throwing-funktioner. Kompilatorn kräver att try befinner sig i en kontext där felet kan fångas.

try? — konvertering till Optional

try? konverterar resultatet av en throwing-funktion till Optional. Om funktionen kastar ett fel returnerar try? nil, annars — Optional med ett lyckat värde. Användbart för anrop där felet kan ignoreras men en indikator på framgång behövs.

try! — tvångsutförande

try! undertrycker felhantering. Om throwing-funktionen kastar ett fel avslutas applikationen med ett runtime-fel. Använd try! endast när du är absolut säker på att felet är omöjligt — till exempel vid inläsning av en inbäddad resurs.

swift
// try? — ignorerar felet, får nil vid fel
if let data = try? Data(contentsOf: url) {
    processData(data)
}

// try! — endast om felet är garanterat omöjligt
let bundled = try! String(contentsOfFile: "Assets/default.txt")

// try — standardalternativ i do-catch
do {
    let result = try performNetworkRequest()
    updateUI(result)
} catch {
    showError(error)
}

Do-Catch i iOS-utveckling: praktiska exempel

Do-Catch används aktivt i iOS-utveckling för arbete med system-API:er. Låt oss titta på typiska scenarier: arbete med filsystemet, Core Data och nätverksförfrågningar.

Filsystem

Många metoder i FileManager är throwing. Do-Catch gör det möjligt att korrekt hantera saknade filer, upptagna resurser eller otillräckliga behörigheter.

Nätverksförfrågningar med Codable

JSON-tolkning via JSONDecoder — en throwing-operation. Do-Catch fångar avkodningsfel och nätverksfel separat och ger användaren exakt feltext.

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)
}

// Anrop med hantering
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)
}

Vanliga misstag vid arbete med Do-Catch

Utvecklare, särskilt de som kommer från andra språk, gör ofta karakteristiska misstag när de använder Do-Catch. Låt oss titta på de vanligaste.

  • Glömd try — anrop av en throwing-funktion utan try leder till kompileringsfel. Swift tillåter inte implicit ignorering av fel.
  • Tom catch — ett catch-block utan hantering döljer felet. Logga eller hantera alltid felet, även om det verkar omöjligt.
  • Catch utan matchning — en enda generell catch för alla fel berövar fördelarna med typsäkerhet. Separera hanteringen efter typ genom flera block.
  • Överdriven användning av try! — try! i produktionskod är en källa till oväntade krascher. Använd endast för inbäddade resurser eller tester.

Vanliga frågor

Vad skiljer Do-Catch i Swift från try-catch i andra språk?

I Swift är ett fel ett värde som motsvarar Error-protokollet, inte ett exception med stackavveckling. Throwing-funktioner måste explicit markeras med throws och kompilatorn kräver try vid anrop — detta eliminerar ohanterade fel i kompileringsfasen.

Kan Do-Catch användas med async/await?

Ja, async-funktioner kan också vara throws och do-catch fungerar för dem. Anrop av en async throwing-funktion kräver try await inuti ett do-block. Detta är standardsättet för felhantering i asynkron Swift-kod.

Hur hanterar man ett fel utan do-catch?

Det finns alternativ: try? omvandlar felet till nil, try! orsakar en crash vid fel och rethrows gör det möjligt att propagerar felet från en closure. Do-catch förblir det primära sättet för explicit hantering.

Kan en funktion kasta olika typer av fel?

Swift typifierar inte kastade fel — vilken throwing-funktion som helst kan kasta vilken typ som helst som motsvarar Error. Separera hanteringen genom matchning i catch mot specifika feltyper.

Är det värt att slå in alla fel i en egen anpassad typ?

Ja, detta är bästa praxis. Definiera AppError som en enum med Error-bekräftelse och konvertera systemfel till domänfel. Detta förenar hanteringen och isolerar applikationslagret från systemdetaljer.

Sammanfattning

  • Do-Catch — Swift-konstruktion för felhantering med obligatorisk throws-markering på funktioner och try vid anrop.
  • Swift-fel — värden som motsvarar Error-protokollet, inte undantag med stackavveckling, vilket ger noll overhead vid frånvaro av fel.
  • Flera catch gör det möjligt att separat hantera olika feltyper med pattern-matching analogt med switch.
  • try? omvandlar felet till nil för enkla scenarier, try! — tvångsanrop med crash-risk, endast använt för garanterat framgångsrika operationer.
  • Do-Catch med async/await — standardsättet för felhantering i asynkron Swift-kod med try await.
  • Undvik tomma catch och överdriven användning av try! — detta döljer fel och leder till oväntade fel i produktion.

Vi utvecklar en mobil applikation nyckelfärdigt

IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.

Diskutera projektet

Läs också