---
title: 'Hata Ayıklama Temelleri'
source: 'https://academia.sh/tr/kurslar/ios-platformu/hata-ayiklama-temelleri'
course: 'iOS Platformu ve Araçlar'
language: tr
updated: '2026-10-21T05:03:10+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - 'İki kaynaktan gelen kesme noktalarının birleştiğini ölçer'
    - 'Düzey ve kategori süzgeçlerinin kesişimini gösterir'
    - 'Şemadaki ortam değişkeninin kodun varsayılanına üstün geldiğini ölçer'
    - 'Adımlama sırasının modelin dışında kaldığını gösterir'
---

# Hata Ayıklama Temelleri

Kesme noktalarının birleşimi, günlük süzgeçlerinin kesişimi, şema ortam değişkeninin üstünlüğü ve kodu olmayan satıra konan kesme noktasının reddi ölçülür.

Uygulama simülatörde ya da aygıtta çalışırken beklenmedik bir şey olduğunda sorunu bulmak için **hata ayıklayıcı (debugger)** kullanılır. En temel araç **kesme noktasıdır (breakpoint)**: çalışmayı belirli bir kod satırında durdurur ve o andaki değerleri incelemeyi sağlar. Durduktan sonra kod satır satır **adımlanır**, çıktı ise **günlüğe (log)** yazılan iletilerden okunur.

Ölçü ekseni değişmez: iki tanım buluşunca nasıl çözülüyor? Bu derste buluşan tanımlar kesme noktası kümeleri, günlük süzgeçleri ve hata ayıklama ayarlarıdır.

## Sınıflandırıcı

```swift
// Meeting.swift — iki tanim bulusunca nasil cozuldugunu siniflandirir
struct Meeting {
    let label: String
    let first: Set<String>
    let second: Set<String>
    let result: Set<String>?

    init(_ label: String, first: Set<String>, second: Set<String>, result: Set<String>?) {
        self.label = label
        self.first = first
        self.second = second
        self.result = result
    }

    var resolution: String {
        if first.isEmpty || second.isEmpty
            || first.isSubset(of: second) || second.isSubset(of: first) {
            return "olcum-disi"
        }
        guard let result, !result.isEmpty else { return "ret" }
        if result == first.union(second) { return "birlesim" }
        if result == first.intersection(second) { return "kesisim" }
        if result == first || result == second { return "oncelik" }
        return "kural-disi"
    }

    static func list(_ values: Set<String>) -> String {
        values.isEmpty ? "bos" : values.sorted().joined(separator: ",")
    }

    func report() {
        let outcome = result.map(Meeting.list) ?? "yok"
        print("\(label): ilk \(Meeting.list(first)) | ikinci \(Meeting.list(second)) | sonuc \(outcome) -> \(resolution)")
    }
}

func summarize(_ meetings: [Meeting]) {
    for resolution in ["oncelik", "kesisim", "birlesim", "ret"] {
        let count = meetings.filter { $0.resolution == resolution }.count
        print("\(resolution): \(count)")
    }
}
```

## Kesme Noktaları

Bir kesme noktası bir dosyanın bir satırına konur. Gerçekte kesme noktaları iki yerden gelebilir: geliştirici ortamının kenar boşluğuna tıklanarak konanlar ve hata ayıklayıcı komut satırından `breakpoint set` ile eklenenler. İkisi aynı projede bir araya geldiğinde etkin olan kesme noktaları kümesi iki kaynağın birleşimidir. Aynı satıra iki kaynaktan da konmuş bir nokta bir kez sayılır.

Model her kesme noktasını `dosya:satır` kimliğiyle gösterir. İlk kaynak sepet dosyasında on ikinci ve otuzuncu satırlara, ikinci kaynak sepet dosyasının otuzuncu ve sipariş dosyasının sekizinci satırına nokta koyar.

```swift
// main.swift — iki kaynagin kesme noktalari birlesir
let gutter: Set<String> = ["Cart.swift:12", "Cart.swift:30"]
let console: Set<String> = ["Cart.swift:30", "Order.swift:8"]

let breakpoints = Meeting(
    "breakpoint-sources",
    first: gutter,
    second: console,
    result: gutter.union(console)
)
breakpoints.report()
```

```
breakpoint-sources: ilk Cart.swift:12,Cart.swift:30 | ikinci Cart.swift:30,Order.swift:8 | sonuc Cart.swift:12,Cart.swift:30,Order.swift:8 -> birlesim
```

Çözüm **birleşim**: üç ayrı nokta etkin. Ortak `Cart.swift:30` bir kez sayıldı. Durma sayısı bu yüzden kaynak sayısının toplamı değildir: iki kaynakta da tanımlı bir nokta tek kez durdurur.

**GO17.** Ölçüm kesme noktalarını dosya ve satır kimliği olarak ele aldı. Koşullu kesme noktaları, hata ayıklayıcıya özgü eylemler ve noktanın devre dışı bırakılması ölçülmedi.

## Kesme Noktası Türleri

Düz bir kesme noktası her ulaşıldığında durur. Döngü içinde ya da sık çağrılan bir işlevde bu, yüzlerce gereksiz durmaya yol açar. İki tür bunu çözer.

- **Koşullu kesme noktası (conditional breakpoint):** Yalnız verilen ifade doğru olduğunda durur. Komut satırında koşul `-c` bayrağıyla verilir: `breakpoint set -f Cart.swift -l 30 -c 'count > 3'`. Koşul her ulaşıldığında hesaplanır; bu yüzden çok sık geçilen bir satırda koşulun kendisi yavaşlığa neden olabilir.
- **Eylemli kesme noktası (action breakpoint):** Durmadan önce ya da durmak yerine bir eylem yürütür. Eylem bir ifadenin değerini yazdırmak, bir komut çalıştırmak ya da bir ses çalmak olabilir. Noktaya otomatik devam seçeneği eklenirse uygulama durmaz; nokta, koda dokunmadan geçici bir günlük satırı gibi davranır. Komut satırında `breakpoint command add` bu işi görür.

İki kesme noktası çeşidi daha vardır. **Özel durum noktası (exception breakpoint)** uygulama bir özel durum fırlattığı anda, çökmeden önce durur; çökme izinde yalnızca sonucu değil nedeni görmeyi sağlar. **Sembolik nokta (symbolic breakpoint)** satır yerine bir işlevin adına konur, böylece kaynağı elde olmayan bir sistem işlevinin her çağrılışında durulabilir. İkisi de bir dosya ve satır kimliği taşımadığı için aşağıdaki ölçümün dışındadır.

Bir noktayı silmeden **devre dışı bırakmak (disable)** da mümkündür. Devre dışı nokta tanımını korur ama durdurmaz; sorun çözülünce silinir, tekrar gerekirse yeniden açılır.

Bu çeşitlerin hiçbiri yukarıdaki ölçümün konusu değildir. Ölçüm noktanın yalnızca konumuna bakar; koşulun doğru çıkıp çıkmadığı çalışma anına aittir ve bir kümeyle ifade edilemez.

## Günlük Süzgeçleri

Uygulama çalışırken çok sayıda ileti yazar. Okunabilir kalması için iki süzgeç birlikte kullanılır: **düzey (level)** süzgeci belirli bir ciddiyetin altındaki iletileri eler, **kategori (category)** süzgeci belirli bir alt sistemin iletilerini tutar. Bir ileti ancak iki süzgeçten de geçerse görünür. Günlüğe yazan kod platformun günlük çerçevesine bağlıdır, bu yüzden yalnız kaynak olarak durur.

```swift
// günlük — KAYNAK
import os

let logger = Logger(subsystem: "com.example.shop", category: "cart")
logger.info("sepet guncellendi")
```

Model her iletiyi bir kimlikle gösterir. Düzey süzgeci uyarı ve üstü iletileri tutar; kategori süzgeci sepet alt sisteminin iletilerini tutar.

```swift
// main.swift — duzey ve kategori suzgeclerinin kesisimi
let levelPass: Set<String> = ["m2", "m3", "m5", "m6"]
let categoryPass: Set<String> = ["m3", "m4", "m5"]

let filters = Meeting(
    "log-filters",
    first: levelPass,
    second: categoryPass,
    result: levelPass.intersection(categoryPass)
)
filters.report()
```

```
log-filters: ilk m2,m3,m5,m6 | ikinci m3,m4,m5 | sonuc m3,m5 -> kesisim
```

Çözüm **kesişim**: yalnız iki süzgeçten de geçen iki ileti görünür. Süzgeçlerden biri gevşetilirse görünen küme genişler; biri sıkılaştırılırsa daralır. Bir iletinin görünmemesi, yazılmadığı anlamına gelmez; yalnız süzgeçlerden birini geçemediğini söyler.

**GO18.** Ölçüm iki süzgeci ayrı kümeler olarak aldı. Süzgeçlerin birbirine bağlı olduğu durumlar ve iletinin birden çok kategoriye ait olması ölçülmedi.

Süzgeçler tek başına yeterli değildir; iletinin hangi düzeyde yazıldığı da önemlidir. Platformun günlük çerçevesi iletileri ciddiyet sırasına göre ayırır.

- **Hata ayıklama düzeyi (debug):** Yalnız geliştirme sırasında işe yarayan ayrıntılar. Yayın sürümünde genellikle saklanmaz.
- **Bilgi düzeyi (info):** Olağan akışta bilinmesi yararlı olan olaylar.
- **Bildirim düzeyi (notice):** Varsayılan düzeydir; sorun olmayan ama kayda değer durumlar.
- **Hata düzeyi (error):** Bir işlemin başarısız olduğu durumlar.
- **Ciddi hata düzeyi (fault):** Uygulamanın ya da sistemin tutarlılığını bozan, hemen müdahale isteyen durumlar.

Kategori ise bir alt sistemin adıdır: ağ, veri tabanı, arayüz gibi. Uygulama kendi alt sistemlerini ve kategorilerini tanımlar. İyi bir adlandırma, sorun çıktığında yalnız ağ iletilerine bakmayı mümkün kılar. Kişisel veri içeren iletiler varsayılan olarak gizlenir; geliştirici açıkça belirtmedikçe değerleri günlükte görünmez.

## Şemadaki Ortam Değişkeni

Çalıştırma ayarları şemada tutulur. Şema, uygulama başlarken ortam değişkenleri verebilir. Kod bir ayar için varsayılan bir değer taşıyorsa ve şema aynı ayar için değer veriyorsa, çalışma sırasında şemadaki değer kodunkinin yerine geçer. Bu yerine koyma bir **önceliktir (precedence)**: ayrıntılı günlüğü kodu değiştirmeden açıp kapatmak bu yüzden mümkündür.

```swift
// main.swift — sema ortam degiskeni kodun varsayilanina ustun gelir
func effectiveLogging(codeDefault: String, schemeValue: String?) -> String {
    schemeValue ?? codeDefault
}

let chosen = effectiveLogging(codeDefault: "verbose-off", schemeValue: "verbose-on")
let environment = Meeting(
    "scheme-environment",
    first: ["verbose-off"],
    second: ["verbose-on"],
    result: [chosen]
)
environment.report()
```

```
scheme-environment: ilk verbose-off | ikinci verbose-on | sonuc verbose-on -> oncelik
```

Çözüm **öncelik**: sonuç ikinci tanımla aynı. Şemadaki değer olmasaydı kodun varsayılanı geçerli olurdu. Şema geliştiriciye özgü olabildiği için, paylaşılmayan bir şemadaki ortam değişkeni başka bir geliştiricide görünmez; "bende çalışıyor" türü farklar bazen buradan çıkar.

**GO19.** Ölçüm tek bir ayar çiftini kapsadı. Birden çok ortam değişkeninin birbirini etkilediği durumlar ve uygulamanın bir ayarı kendi içinde yeniden okuması ölçülmedi.

## Kodu Olmayan Satır

Her satıra kesme noktası konamaz. Boş bir satır, yorum satırı ya da tek başına bir süslü parantez çalıştırılabilir kod üretmez; hata ayıklayıcı noktayı en yakın kod satırına kaydırır ya da hiç etkin yapmaz. Model bu davranışı kesin bir kural olarak değil, bir buluşma olarak ölçer: istenen satır ile kod içeren satırların kümesi buluşur.

```swift
// main.swift — kodu olmayan satira konan kesme noktasi
let codeLines: Set<String> = ["10", "11", "13"]
let requested: Set<String> = ["12"]

let emptyLine = Meeting(
    "breakpoint-on-empty-line",
    first: requested,
    second: codeLines,
    result: requested.intersection(codeLines)
)
emptyLine.report()
```

```
breakpoint-on-empty-line: ilk 12 | ikinci 10,11,13 | sonuc bos -> ret
```

Ortak satır yok ve çözüm **ret**: on ikinci satırda durulacak bir kod bulunmuyor. Hata ayıklayıcının noktayı komşu satıra kaydırması bu modelin dışında kalır; model noktanın istenen satırda kalıp kalmadığını sayar.

## Adımlama Komutları ve Değişken İnceleme

Uygulama bir noktada durduğunda üç temel komut ilerlemeyi yönetir. Hata ayıklayıcı komut satırındaki karşılıkları ters tırnak içinde verilmiştir.

- **İçine gir (step into):** `step` komutu. Geçerli satırdaki çağrının gövdesine girer ve ilk satırında durur.
- **Üzerinden atla (step over):** `next` komutu. Çağrıyı tek adımda yürütür, bir sonraki satırda durur. Çağrının içinde bir kesme noktası varsa orada yine durulur.
- **Dışına çık (step out):** `finish` komutu. Geçerli işlevin dönmesine kadar çalışır ve çağıranın satırında durur.

Bir çağrının içeriğiyle ilgileniyorsanız içine girersiniz; ilgilenmiyorsanız üzerinden atlarsınız; yanlışlıkla çok derine indiyseniz dışına çıkarsınız. Standart kitaplık gibi bilmediğiniz kodun içine girmek çoğu zaman zaman kaybettirir.

Durduktan sonra değer incelenir. `frame variable` geçerli çerçevedeki yerel değişkenleri listeler. `print` bir ifadeyi değerlendirir. `po` ifadenin nesne olarak yazdırılabilir betimlemesini verir; tür kendi betimlemesini sağlıyorsa bu daha okunur olur. Değişken penceresi aynı bilgiyi grafik olarak gösterir. Çağrı zinciri gezilerek üst çerçevelerin değişkenleri de görülür. Değer değiştirmek de mümkündür; `expression count = 0` gibi bir ifade uygulamayı yeniden derlemeden bir varsayımı sınar.

Bu komutların hepsi çalışan bir süreçle konuşur, bu nedenle modelde karşılığı yoktur. Aşağıdaki ölçüm yalnız adımlamanın bıraktığı izi, yani hangi satırların ziyaret edildiğini sayar.

## Sınırlayıcı Ölçüm

Adımlama kodu satır satır ilerletir. **Üzerinden atlamak** bir çağrıyı tek adımda yürütür, **içine girmek** çağrının gövdesine iner. Aynı satırları ziyaret eden iki adımlama, farklı bir sırayla ilerleyebilir. Model ziyaret edilen satırların kümesini sayar; sırayı sayamaz. İki ziyaret dizisini basalım, sonra kümelerini buluşturalım.

```swift
// main.swift — adimlama sirasi modelde gorunmez
let overOrder = ["10", "11", "13"]
let intoOrder = ["13", "10", "11"]
print("step-over: " + overOrder.joined(separator: ","))
print("step-into: " + intoOrder.joined(separator: ","))

let stepping = Meeting(
    "stepping-order",
    first: Set(overOrder),
    second: Set(intoOrder),
    result: Set(overOrder)
)
stepping.report()
```

```
step-over: 10,11,13
step-into: 13,10,11
stepping-order: ilk 10,11,13 | ikinci 10,11,13 | sonuc 10,11,13 -> olcum-disi
```

İki dizi farklı sırada ilerledi ama aynı üç satırı ziyaret etti. Kümeler aynı olduğu için sınıflandırıcı bir buluşma görmedi: sonuç **ölçüm dışı**. Sıra, bir hatanın nerede ortaya çıktığını belirlemede önemli olabilir; model onu saymaz.

**GO20.** Ölçüm ziyaret edilen satırların kümesini saydı. Adımların sırası, tekrar eden ziyaretler ve çağrı içinde geçen süre ölçülmedi.

## Özet

- İki kaynaktan gelen kesme noktaları birleşir; ortak nokta bir kez sayılır.
- Düzey ve kategori süzgeçlerinden ikisini de geçen iletiler görünür; çözüm kesişimdir.
- Şemadaki ortam değişkeni kodun varsayılanının yerini alır.
- Kodu olmayan satıra istenen kesme noktası model içinde reddedilir.
- Bu dersin çözümü: **birleşim**. Adımlama sırası ise ölçümün dışında kalır.

## Sonraki Adım

Bu derste çalışan uygulama içinde hata arandı. Son derste iki dilin aynı projede buluşması ele alınacak: aynı Objective-C seçicisine düşen iki Swift yönteminin sonucu ölçülür.
