Do-Catch: шта је то, конструкција и обрада грешака у Swift-у

Аутор: IT Sectr Објављено: 2026-05-26 Време читања: 8 мин

Do-Catch — конструкција језика Swift за обраду грешака, која хвата изузетке бачене путем throw и извршава одговарајући блок кода. За разлику од традиционалних try-catch у другим језицима, Swift захтева експлицитно означавање функција које могу бацити грешку модификатором throws. Према Swift.org, 2026, Do-Catch је основни механизам обраде грешака у Swift-у, који обезбеђује безбедност на нивоу типова.

Главно

  • Do-Catch — конструкција Swift-а која хвата грешке из блокова са try и throw.
  • throws — маркер функције који сигнализира да може бацити грешку.
  • try — кључна реч за позивање throwing функције унутар do блока.
  • catch — блок обраде грешке са могућношћу поређења по типу.
  • try? и try! — алтернативни облици који претварају грешку у nil или изазивају crash.

Шта је Do-Catch?

Do-Catch — је конструкција у Swift-у која се састоји од блока do, унутар којег се извршава код способан да баци грешку, и једног или више блокова catch који обрађују ту грешку. Do блок садржи позиве throwing функција означене са try, а catch блокови пореде грешку по типу.

Swift имплементира модел структуриране обраде грешака, различит од изузетака у Objective-C-у. Овде грешка није exception са одмотавањем стека, већ вредност која одговара протоколу Error. Бацање грешке путем throw преноси контролу на најближи catch блок без трошкова одмотавања стека.

Кључна карактеристика Swift-а — експлицитност обраде. Компајлер не дозвољава позивање throwing функције без try, do-catch или алтернативног механизма (try?, try!). Ово елиминише ситуације у којима грешка остаје непримећена.

Модел грешака у Swift-у: Error протокол и throwing функције

У основи обраде грешака у Swift-у лежи протокол Error. Било који тип који одговара овом протоколу може бити бачен путем throw. Обично се грешке дефинишу као enum са потврдом Error.

Протокол Error

Error — празан протокол (маркерни). Не захтева имплементацију метода, само потврду усаглашености. Swift компајлер користи Error за статичку проверу: функција са throws може бацити само вредност која одговара Error-у.

Throwing функције

Функција означена са throws мора бити позвана са try. Ако унутар такве функције дође до throw, контрола се преноси у позивајући do-catch. Ако грешка није обрађена нигде у ланцу позива, преноси се на виши ниво.

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

Пренос грешке rethrows

rethrows — модификатор за функције које примају throwing затварање као параметар. Ако прослеђено затварање не баца грешку, rethrows функција се може позвати без try. Ово омогућава писање генеричких функција вишег реда компатибилних са throwing и non-throwing затварањима.

Синтакса Do-Catch-а: више catch блокова

Swift подржава вишеструке catch блокове са поређењем по типу грешке. Ово личи на when у Kotlin-у или switch по типу: први одговарајући catch се извршава, остали се прескачу.

Поређење по типу

Сваки catch блок може садржати шаблон поређења са одређеним типом грешке. Swift проверава блокове редом, тако да специфичнији типови треба да буду испред општих. Ако ниједан шаблон не одговара, извршава се catch блок без шаблона.

Обрада више типова

Типска безбедност Do-Catch-а омогућава обраду сваке грешке појединачно или комбиновање више типова у једном блоку кроз зарез у pattern-matching-у. Ово елиминише гломазне if-else ланце карактеристичне за Objective-C, где се анализа грешке вршила путем повратног кода или NSError са провером domain и code.

Swift такође подржава catch where — поређење са додатним условом. На пример, могуће је филтрирати грешке по одређеном коду или тексту: catch URLError where error.code == .notConnectedToInternet. Ово смањује број catch блокова уз задржавање прецизности обраде.

За отклањање грешака у throwing функцијама, Swift пружа разлику између грешака и изузетака. Грешка у Swift-у — повратна вредност која не захтева одмотавање стека. Iзузеци у Objective-C (@try/@catch) раде на нивоу runtime-а и користе се само за фаталне отказе. Do-Catch обрађује управо грешке, а не изузетке, што га чини предвидивим и перформантним.

При развоју библиотека и SDK-а, важно је запамтити да су throwing функције део јавног уговора. Тип грешке није специфициран у потпису, зато документујте које грешке функција може бацити у коментару или путем Result-сличног enum-а. Ово помаже корисницима API-ја да пишу исправне catch блокове без задирања у имплементацију.

У контексту асинхроног програмирања, Do-Catch са async/await решава проблем callback hell. Раније је у Swift-у обрада грешака у асинхроном коду захтевала угнежђена затварања са провером Error? у completion handler-у. Са async/await и Do-Catch-ом, асинхрони throwing код изгледа као синхрони, што поједностављује читање и одржавање сложених ланаца захтева са обрадом грешака на сваком кораку.

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("Непозната грешка: \(error)")
}

Try варијације: try, try?, try! и када их користити

Swift нуди три варијанте позивања throwing функција: try, try? и try!. Свака варијанта решава одређени задатак и има своја ограничења.

try — стандардни позив

try се користи унутар do блока, а грешка се обрађује у catch-у. Ово је основни начин позивања throwing функција. Компајлер захтева да try буде у контексту где грешка може бити ухваћена.

try? — конверзија у Optional

try? претвара резултат throwing функције у Optional. Ако функција баци грешку, try? враћа nil, иначе — Optional са успешном вредношћу. Погодно за позиве где грешка може бити игнорисана, али је потребан индикатор успеха.

try! — принудно извршење

try! потискује обраду грешака. Ако throwing функција баци грешку, апликација се завршава са runtime грешком. Користите try! само када сте апсолутно сигурни да је грешка немогућа — на пример, при учитавању уграђеног ресурса.

swift
// try? — игноришемо грешку, добијамо nil при отказу
if let data = try? Data(contentsOf: url) {
    processData(data)
}

// try! — само ако је грешка гарантовано немогућа
let bundled = try! String(contentsOfFile: "Assets/default.txt")

// try — стандардна опција у do-catch-у
do {
    let result = try performNetworkRequest()
    updateUI(result)
} catch {
    showError(error)
}

Do-Catch у iOS развоју: практични примери

Do-Catch се активно користи у iOS развоју за рад са системским API-јима. Размотримо типичне сценарије: рад са фајл системом, Core Data и мрежним захтевима.

Фајл систем

Многе методе FileManager-а су throwing. Do-Catch омогућава правилну обраду недостатка фајла, заузетости ресурса или недостатка дозвола.

Мрежни захтеви са Codable

Парсирање JSON-а путем JSONDecoder — throwing операција. Do-Catch хвата грешке декодирања и мрежне отказе одвојено, пружајући кориснику прецизан текст грешке.

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

// Позив са обрадом
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)
}

Типичне грешке при раду са Do-Catch-ом

Програмери, посебно они који прелазе са других језика, често праве карактеристичне грешке при коришћењу Do-Catch-а. Размотримо најчешће.

  • Заборављен try — позив throwing функције без try-а доводи до greške компајлације. Swift не дозвољава имплицитно игнорисање грешака.
  • Празан catch — catch блок без обраде скрива грешку. Увек логирајте или обрађујте грешку, чак и ако изгледа немогуће.
  • Catch без поређења — један општи catch за све грешке лишава предности типске безбедности. Раздвајајте обраду по типовима кроз више блокова.
  • Претерана употреба try! — try! у production коду је извор неочекиваних crash-ева. Користите само за уграђене ресурсе или тестове.

Често постављана питања

По чему се Do-Catch у Swift-у разликује од try-catch у другим језицима?

У Swift-у грешка је вредност која одговара протоколу Error, а не exception са одмотавањем стека. Throwing функције морају бити експлицитно означене са throws, а компајлер захтева try при позиву — ово елиминише необрађене грешке у фази компајлације.

Може ли се Do-Catch користити са async/await?

Да, async функције такође могу бити throws, и do-catch ради за њих. Позив async throwing функције захтева try await унутар do блока. Ово је стандардни начин обраде грешака у асинхроном Swift коду.

Како обрадити грешку без do-catch-а?

Постоје алтернативе: try? претвара грешку у nil, try! изазива crash при грешци, а rethrows омогућава пренос грешке из затварања. Do-catch остаје основни начин експлицитне обраде.

Може ли једна функција бацати различите типове грешака?

Swift не типизира бачене грешке — свака throwing функција може бацити било који тип који одговара Error-у. Раздвајајте обраду кроз поређење у catch-у са одређеним типовима грешака.

Да ли вреди умотавати све грешке у свој прилагођени тип?

Да, ово је најбоља пракса. Дефинишите AppError као enum са потврдом Error и конвертујте системске грешке у доменске. Ово уједињује обраду и изолује слој апликације од системских детаља.

Закључци

  • Do-Catch — конструкција Swift-а за обраду грешака са обавезним означавањем throws на функцијама и try при позиву.
  • Грешке у Swift-у — вредности које одговарају протоколу Error, а не изузеци са одмотавањем стека, што даје нулте трошкове при одсуству отказа.
  • Вишеструки catch омогућавају одвојену обраду различитих типова грешака са pattern-matching-ом аналогним switch-у.
  • try? претвара грешку у nil за једноставне сценарије, try! — принудни позив са ризиком од crash-а, коришћен само за гарантовано успешне операције.
  • Do-Catch са async/await — стандардни начин обраде грешака у асинхроном Swift коду са коришћењем try await.
  • Избегавајте празне catch и претерану употребу try! — ово скрива грешке и доводи до неочекиваних отказа у production-у.

Развићемо мобилну апликацију под кључ

IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.

Разговарајте о пројекту

Прочитајте такође