Do-Catch — конструкција језика Swift за обраду грешака, која хвата изузетке бачене путем throw и извршава одговарајући блок кода. За разлику од традиционалних try-catch у другим језицима, Swift захтева експлицитно означавање функција које могу бацити грешку модификатором throws. Према Swift.org, 2026, Do-Catch је основни механизам обраде грешака у Swift-у, који обезбеђује безбедност на нивоу типова.
Главно
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. Било који тип који одговара овом протоколу може бити бачен путем throw. Обично се грешке дефинишу као enum са потврдом Error.
Error — празан протокол (маркерни). Не захтева имплементацију метода, само потврду усаглашености. Swift компајлер користи Error за статичку проверу: функција са throws може бацити само вредност која одговара Error-у.
Функција означена са throws мора бити позвана са try. Ако унутар такве функције дође до throw, контрола се преноси у позивајући do-catch. Ако грешка није обрађена нигде у ланцу позива, преноси се на виши ниво.
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 — модификатор за функције које примају throwing затварање као параметар. Ако прослеђено затварање не баца грешку, rethrows функција се може позвати без try. Ово омогућава писање генеричких функција вишег реда компатибилних са throwing и non-throwing затварањима.
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 код изгледа као синхрони, што поједностављује читање и одржавање сложених ланаца захтева са обрадом грешака на сваком кораку.
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)")
}
Swift нуди три варијанте позивања throwing функција: try, try? и try!. Свака варијанта решава одређени задатак и има своја ограничења.
try се користи унутар do блока, а грешка се обрађује у catch-у. Ово је основни начин позивања throwing функција. Компајлер захтева да try буде у контексту где грешка може бити ухваћена.
try? претвара резултат throwing функције у Optional. Ако функција баци грешку, try? враћа nil, иначе — Optional са успешном вредношћу. Погодно за позиве где грешка може бити игнорисана, али је потребан индикатор успеха.
try! потискује обраду грешака. Ако throwing функција баци грешку, апликација се завршава са runtime грешком. Користите try! само када сте апсолутно сигурни да је грешка немогућа — на пример, при учитавању уграђеног ресурса.
// 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 развоју за рад са системским API-јима. Размотримо типичне сценарије: рад са фајл системом, Core Data и мрежним захтевима.
Многе методе FileManager-а су throwing. Do-Catch омогућава правилну обраду недостатка фајла, заузетости ресурса или недостатка дозвола.
Парсирање JSON-а путем JSONDecoder — throwing операција. Do-Catch хвата грешке декодирања и мрежне отказе одвојено, пружајући кориснику прецизан текст грешке.
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-а. Размотримо најчешће.
Често постављана питања
У Swift-у грешка је вредност која одговара протоколу Error, а не exception са одмотавањем стека. Throwing функције морају бити експлицитно означене са throws, а компајлер захтева try при позиву — ово елиминише необрађене грешке у фази компајлације.
Да, async функције такође могу бити throws, и do-catch ради за њих. Позив async throwing функције захтева try await унутар do блока. Ово је стандардни начин обраде грешака у асинхроном Swift коду.
Постоје алтернативе: try? претвара грешку у nil, try! изазива crash при грешци, а rethrows омогућава пренос грешке из затварања. Do-catch остаје основни начин експлицитне обраде.
Swift не типизира бачене грешке — свака throwing функција може бацити било који тип који одговара Error-у. Раздвајајте обраду кроз поређење у catch-у са одређеним типовима грешака.
Да, ово је најбоља пракса. Дефинишите AppError као enum са потврдом Error и конвертујте системске грешке у доменске. Ово уједињује обраду и изолује слој апликације од системских детаља.
Закључци
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође