Try-Catch — potensial təhlükəli kodu qorunan blokda icra etməyə və səhvləri proqramın qəzaya uğraması olmadan düzgün idarə etməyə imkan verən istisna tutma konstruksiyasıdır. Try bloku istisna ata bilən kodu ehtiva edir, catch onu tutur və bərpa məntiqini yerinə yetirir. Apple Swift Documentation (2026)-ya görə, finally bloku istisnanın atılmasından və ya atılmamasından asılı olmayaraq icra olunur, resursların sərbəst buraxılmasını təmin edir.
Əsas Məqamlar
Try-Catch — müasir proqramlaşdırma dillərinin əksəriyyətində mövcud olan strukturlaşdırılmış istisna idarəetməsinin əsas konstruksiyasıdır. Üç blokdan ibarətdir: try (təhlükəli kodu icra etmə cəhdi), catch (istisnanı tutma və emal etmə) və isteğe bağlı finally (sonlandırma). Konstruksiyanın ideyası biznes əməliyyatlarının məntiqini səhv idarəetmə məntiqindən ayırmaq, kodu daha oxunaqlı və proqnozlaşdırıla bilən etməkdir.
Konsepsiya ilk dəfə C++ dilində try/catch kimi tətbiq edilmiş, sonra Java, C#, Swift, Kotlin, Dart, Python, JavaScript və digər dillər tərəfindən mənimsənilmişdir. Hər bir dil öz xüsusiyyətlərini əlavə edir: Swift-də catch bloku hərtərəfli olmalıdır, Kotlin-də try-catch ifadə (expression) ola bilər, Dart-da axın resursları üçün finally məcburidir. Fərqlərə baxmayaraq, əsas prinsip eynidir: səhv yarandığı yerə mümkün qədər yaxın idarə olunur, qlobal deyil.
Try-Catch istifadəsi xüsusilə mobil inkişafda aktualdır, burada xarici amillər — şəbəkə itkisi, serverdən düzgün olmayan cavab, yaddaş çatışmazlığı — daim baş verir. Düzgün istisna idarəetməsi proqramın qəzalarının qarşısını alır və düzgün UX təmin edir: istifadəçi proqramın qəflətən bağlanması əvəzinə səhv mesajı alır. Google Android Kotlin Style Guide (2026)-ya görə, istisna ata bilən hər bir funksiya ya try-catch vasitəsilə onu emal etməli, ya da imzada throws bəyan etməlidir.
Try-catch-in işləmə mexanizmi stack-in açılmasına (stack unwinding) əsaslanır. Try bloku daxilində throw operatoru (və ya sistem səhvi nəticəsində) istisna atıldıqda, normal icra axını dərhal dayandırılır. İcra uyğun catch bloku axtarışında zənglər yığınında bir səviyyə yuxarı hərəkət edir. Müasir dillər atılmış istisnanın tipinə uyğun gələn tipdə catch axtarır, tip uyğunlaşdırma mexanizmindən (type matching) istifadə edərək.
Müvafiq catch tapılarsa, onun gövdəsi icra olunur, bundan sonra icra bütün try-catch-finally konstruksiyasından sonra davam edir. Catch tapılmazsa, istisna yığında daha yuxarı qalxır və daha yüksək səviyyədə idarə oluna bilər — mobil proqramda istifadəçiyə səhv dialoqu göstərən qlobal handler-ə qədər. İstisna heç yerdə idarə olunmazsa, proqram qəzaya uğrayır. Məhz buna görə bütün mümkün istisna tiplərinin düzgün idarə edilməsi proqramın sabitliyi üçün kritikdir.
fun readUserData(): User {
return try {
val response = api.fetchUser()
parseUser(response)
} catch (e: IOException) {
logError("Şəbəkə xətası", e)
throw AppException("Məlumatları yükləmək mümkün olmadı")
} catch (e: JsonParseException) {
logError("Parsing xətası", e)
return User.default()
} finally {
closeLoadingIndicator()
}
}
Kod əvvəlcə API sorğusunu yerinə yetirməyə və cavabı pars etməyə çalışır. IOException (şəbəkə problemi) yaranarsa, istisna loglanır və AppException kimi ötürülür. JsonParseException olarsa — standart istifadəçi qaytarılır. Finally bloku yükləmə göstəricisini gizlətməyə zəmanət verir, ekranda UI komponentlərinin sızmasının qarşısını alır.
Swift-də səhv idarəetməsi Error protokolu (əvvəllər ErrorType) vasitəsilə həyata keçirilir. Error-a uyğun gələn istənilən tip throw operatoru ilə atıla bilər. Səhv ata bilən funksiya imzada throws açar sözü ilə qeyd olunur. Belə funksiyanın çağırılması try (açıq try-catch üçün), try? (isteğe bağlı nəticə) və ya try! (səhv idarəetməsi olmadan məcburi icra) prefiksini tələb edir.
enum NetworkError: Error {
case noConnection
case serverError(code: Int)
case timeout
}
func fetchUser(id: Int) throws -> User {
guard isConnected() else {
throw NetworkError.noConnection
}
let data = try performRequest(path: "/users/\(id)")
return try decodeUser(from: data)
}
do {
let user = try fetchUser(id: 42)
updateUI(user)
} catch NetworkError.noConnection {
showOfflineAlert()
} catch let error as NetworkError {
showError("Şəbəkə " + error.localizedDescription)
} catch {
showGenericError()
}
Enum NetworkError Error protokolunu tətbiq edir, üç hal müəyyənləşdirir: noConnection, kodu ilə serverError və timeout. fetchUser funksiyası throws ilə qeyd olunub: əvvəlcə əlaqəni yoxlayır, sonra sorğu və pars etməni yerinə yetirir. Do-catch blokunda üç catch müxtəlif ssenariləri idarə edir: spesifik noConnection halı, ümumi NetworkError tipi və bütün digər səhvlər. Bu, problem növündən asılı olaraq istifadəçiyə fərqli mesajlar göstərməyə imkan verir.
Kotlin try-catch-finally-ni Java-dan miras aldı, lakin mühüm fərq əlavə etdi: Kotlin-də try-catch ifadədir (expression), təlimat (statement) deyil. Bu o deməkdir ki, try blokunun və ya catch blokunun nəticəsi dəyişənə təyin oluna bilər. Try blokundakı son ifadə uğur halında nəticə olur, catch-dəki son ifadə isə səhv halında. Əgər səhv heç bir catch tərəfindən idarə olunmazsa, istisna yığında yuxarı ötürülür.
sealed class Result<out T> {
data class Success<out T>(val data: T) : Result<T>()
data class Error(val exception: Throwable) : Result<Nothing>()
}
fun loadData(): Result<List<Item>> {
return try {
val response = api.getItems()
Result.Success(response.toList())
} catch (e: HttpException) {
Log.e("HTTP ", e)
Result.Error(e)
} catch (e: IOException) {
Log.e("Şəbəkə ", e)
Result.Error(e)
}
}
Nümunədə sealed class Result uğurlu cavabı və ya səhvi əhatə edir. loadData funksiyası try-catch-i ifadə kimi istifadə edir: uğur halında Result.Success qaytarır, HttpException və ya IOException istisnasında — loglama ilə Result.Error. Bu yanaşma çağıran tərəfə səhvləri istisnasız idarə etməyə imkan verir — Result tipi üzrə when-ifadəsi vasitəsilə. Bu xüsusilə Jetpack Compose-da StateFlow və collectAsState vasitəsilə müxtəlif UI vəziyyətlərini (Loading, Success, Error) göstərmək üçün əlverişlidir.
Dart try-catch-finally-ni Java-ya oxşar sintaksislə dəstəkləyir, lakin dəyişən göstərmədən istisna tipinə görə filtrləmək üçün on bəndinin əlavə edilməsi ilə. Bu, istisnanın özü lazım olmadıqda rahatdır — yalnız onun tipinin faktı vacibdir. Dart həmçinin iki parametrli catch blokunu dəstəkləyir: istisna obyekti və StackTrace, bu da tam çağırış zəncirini loglamaq üçün faydalıdır.
import 'dart:io';
import 'dart:convert';
class UserRepository {
Future<User> fetchUser(String id) async {
try {
final client = HttpClient();
final request = await client.getUrl(
Uri.parse('https://api.example.com/users/$id')
);
final response = await request.close();
final body = await response.transform(utf8.decoder).join();
return User.fromJson(json.decode(body));
} on SocketException catch (e, stackTrace) {
log("No internet", e, stackTrace);
throw AppException("Connection failed");
} on FormatException {
throw AppException("Invalid response format");
} finally {
client.close();
}
}
}
SocketException ətraflı loglama üçün obyektin və StackTrace-in tutulması ilə yaxalanır, sonra AppException kimi ötürülür. FormatException dəyişənsiz yaxalanır — cavab formatının səhv olduğunu bilmək kifayətdir. Finally bloku HttpClient-i bağlamağa zəmanət verir, soket sızmalarının qarşısını alır. Flutter-də bu yanaşma Widget testi üçün xüsusilə vacibdir, burada State.initState-də idarə olunmayan istisnalar bütün test sessiyasının çökməsinə səbəb olur.
Hətta təcrübəli developerlər try-catch ilə işləyərkən yaddaş sızmasına, gizli bug-lara və ya proqramın düzgün olmayan davranışına səbəb olan səhvlərə yol verirlər. Mobil inkişafda ən geniş yayılmış beş problemi nəzərdən keçirək.
Boş catch — ən pis təcrübələrdən biridir. İstisna udulur, proqram səhv vəziyyətdə işləməyə davam edir və developer problemdən xəbərsiz qalır. Həmişə ən azı istisnanı loglayın. Kotlin-də catch(e: Exception) { Log.e(...) }, Swift-də — catch { print($0) } istifadə edin. Dart-da minimal məqbul catch debugPrint çağırmalı və ya Crashlytics-ə yazmalıdır.
Bütün istisnaları tiplərə ayırmadan catch (Exception e) ilə tutmaq gözlənilməz səhvləri — NullPointerException, OutOfMemoryError, StackOverflowError — gizlədir. Yalnız gözlədiyiniz və idarə edə biləcəyiniz tipləri tutun. Qalanları üçün yuxarı yayılmasına icazə verin. Mobil inkişafda IOException, TimeoutException, AuthException üçün spesifik catch istifadəçiyə daha mənalı mesajlar verir.
Resurslar — fayllar, soketlər, DB kursorları, animasiyalar — finally-də və ya use blokunda (AutoCloseable) sərbəst buraxılmalıdır. Developerlər çox vaxt istisna zamanı resursları bağlamağı unudurlar ki, bu da sızmalara səbəb olur. Kotlin-də Closeable resursları üçün .use { }, Swift-də — defer { }, Dart-da — async paketindən await using istifadə edin. Finally bloku hətta catch daxilində istisna atıldıqda da sərbəst buraxılmanı təmin edir.
Asinxron koddakı try-catch digər iplərdən gələn istisnaları tutmur. Kotlin Coroutines-də CoroutineExceptionHandler və ya SupervisorJob istifadə edin. Swift async/await-də — Task daxilində do-catch. Flutter-də — qlobal tutma üçün runZonedGuarded. Bu qaydaya məhəl qoymamaq production-da çətin təkrarlanan qəzaların səbəbidir.
İstisnanın idarə edilməsi istifadəçi interfeysini qeyri-müəyyən müddətə bloklamamalıdır. İstifadəçiyə konkret mesaj göstərin və əməliyyatı təkrarlamaq imkanı verin. Kotlin/Compose-də Retry düyməsi olan Snackbar, Swift-də action ilə UIAlertController, Flutter-də action ilə SnackBar — şəbəkə və ya server səhvləri üçün minimal yetərli UX-dir. Bərpa imkanı olmayan ümumi „Xəta baş verdi" dialoqlarından çəkinin.
Tez-tez verilən suallar
Try-catch səhvləri idarə etmək üçün istisnalar və stack-in açılmasından istifadə edir ki, bu da çox sayda səhv olduqda performans baxımından baha başa gələ bilər. Result Type — stack-in açılması olmadan pattern matching vasitəsilə idarə olunan tip-konteynerdir (Success və ya Failure), gözlənilən səhvlər üçün daha səmərəlidir.
Finally, try bloku bağlanmalı olan resurslar (fayllar, soketlər, kursorlar) açırsa məcburidir. Resurslar açılmırsa, finally tələb olunmur. Müasir dillərdə resursları finally olmadan avtomatik bağlamaq üçün AutoCloseable/use/defer istifadə edin. Kotlin və Swift-də use-bloku Closeable obyektləri üçün finally-ni əvəz edir.
Normal axında (istisnasız) try-catch performansa praktiki olaraq təsir etmir — JVM və Swift compiler bu halı optimallaşdırır. Lakin istisna atıldıqda stack-in açılması baş verir ki, bu da stack-in dərinliyindən asılı olaraq 10–100 µs çəkə bilər. İcra axınını idarə etmək üçün istisnalardan istifadə etməyin — bu anti-nümunədir.
Korutinalarda qlobal tutma üçün coroutineScope daxilində try-catch və ya CoroutineExceptionHandler istifadə edin. SupervisorJob valideyn korutinasının uşaq korutinasındakı səhvə görə ləğv edilməsinin qarşısını alır. Launch üçün CoroutineExceptionHandler, async üçün — await() ətrafında try-catch istifadə edin.
Çoxsaylı catch üstünlük verilir: kod xətti oxunur, hər blok bir tip istisnanı idarə edir. If-else ilə bir catch saxlamaq daha çətindir, yeni istisna tipini qaçırmaq asandır. Swift-də enum Error-un hərtərəfli idarə edilməsi üçün çoxsaylı catch məcburidir, Kotlin-də məhdudiyyət yoxdur, lakin ən yaxşı təcrübə tip üzrə ayrıca catch-dir.
Xülasə
Açar təslim mobil tətbiq hazırlayacağıq
IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.
Həm də oxuyun