---
title: 'Görsel Bileşenler'
source: 'https://academia.sh/tr/kurslar/swiftui/gorsel-bilesenler'
course: 'SwiftUI ile Arayüz'
language: tr
updated: '2026-10-21T05:03:15+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - 'Metin, görsel ve şekil gibi yaprak bileşenlerin kaynak parçada nasıl kurulduğunu okur'
    - 'Renk şemasının simge rengini ortam değeri olarak belirlediğini ölçer'
    - 'Şeklin dolgu oranını veren ebeveyn durumunun ebeveyn tetiği ürettiğini gösterir'
    - 'Yükleniyor durumunun görselin kendisine ait olduğunu ve yerel tetik ürettiğini ölçer'
---

# Görsel Bileşenler

Renk şemasının simge rengini ortam değeri olarak belirlediğinin, şeklin dolgu oranının ebeveynden indiğinin, görselin yükleniyor durumunun yerel kaldığının ve statik görselin hiçbir değer okumadığının ölçümü.

Önceki derste tetik, ağacın dışındaki bir modelden geldi. Bu derste ağacın yapraklarına bakıyoruz: metin, simge, şekil ve görsel. Bu bileşenler başka görünümleri içermez ama değer okur: bir simgenin rengi, bir şeklin dolgusu ve bir görselin yüklenme durumu birer değere bağlıdır. Soru aynı kalır: **bu yeniden hesaplamayı ne tetikledi?** Bu derste bakılan tetik, **ortam**.

```swift
// Invalidation.swift — bir degisikligin hangi gorunumu hangi kaynak yoluyla yeniden hesaplattigini siniflandirir
enum Storage {
    case state(owner: String)
    case model(object: String)
    case environment
}

struct ViewNode {
    let name: String
    let parent: String?
    let reads: Set<String>

    init(_ name: String, parent: String?, reads: Set<String>) {
        self.name = name
        self.parent = parent
        self.reads = reads
    }
}

struct Recompute {
    let view: String
    let cause: String
}

struct ViewTree {
    let nodes: [ViewNode]
    let storage: [String: Storage]

    func ancestors(of name: String) -> [String] {
        var found: [String] = []
        var current = nodes.first { $0.name == name }?.parent
        while let next = current {
            found.append(next)
            current = nodes.first { $0.name == next }?.parent
        }
        return found
    }

    func cause(of node: ViewNode, key: String) -> String {
        guard let kind = storage[key] else { return "olcum-disi" }
        switch kind {
        case .environment:
            return "ortam"
        case .model:
            return "gozlem"
        case .state(let owner):
            if owner == node.name { return "yerel" }
            if ancestors(of: node.name).contains(owner) { return "ebeveyn" }
            return "kural-disi"
        }
    }

    func change(_ label: String, key: String) -> [Recompute] {
        let hits = nodes.filter { $0.reads.contains(key) }
            .map { Recompute(view: $0.name, cause: cause(of: $0, key: key)) }
        let skipped = nodes.filter { !$0.reads.contains(key) }.map(\.name)
        let recomputed = hits.isEmpty ? "yok" : hits.map { "\($0.view) \($0.cause)" }.joined(separator: ", ")
        let rest = skipped.isEmpty ? "yok" : skipped.joined(separator: ",")
        print("\(label): \(key) degisti | yeniden \(recomputed) | atlanan \(rest)")
        return hits
    }
}

func countCauses(_ recomputes: [Recompute]) {
    for cause in ["yerel", "ebeveyn", "gozlem", "ortam"] {
        print("\(cause): \(recomputes.filter { $0.cause == cause }.count)")
    }
}
```

Çekirdek, açılış dersindekiyle aynıdır. Bu dersin ağacı bir gösterge panelidir: paneli kuran ekran, panel, şekil, simge ve avatar.

## Yaprak Bileşenler

Metin, simge, şekil ve görsel ağacın yapraklarıdır. Her biri kendi biçimini ya da içeriğini bir değerden alır. Aşağıdaki parça dördünü bir arada gösterir.

```swift
// Kaynak parca: metin, simge, sekil ve gorsel
import SwiftUI

struct MeterPanel: View {
    let fillRatio: Double

    var body: some View {
        VStack {
            Text("Doluluk")
            Image(systemName: "gauge")
            Capsule()
                .fill(Color.blue)
                .frame(width: 200 * fillRatio, height: 12)
            Image("logo")
        }
    }
}
```

Şeklin genişliği panelin `fillRatio` parametresinden gelir. Simge ise ön plan rengini ortamdan alır. `Image("logo")` bir varlık adıyla kurulan statik bir görseldir ve hiçbir değer okumaz.

**GV20.** Bu ölçüm yaprak bileşenleri okudukları değerler üzerinden ele alır. Bileşenlerin çizim maliyeti, simge kümesinin boyutu ve varlık kataloğunun çözümlenmesi ölçülmedi.

## Renk Şeması ve Dolgu Oranı

Aşağıdaki ağaçta renk şeması ortamdan gelir ve simgeyle avatar tarafından okunur. Dolgu oranı paneli kuran ekranın, `MeterScreen`'in durumudur; panel onu `let` parametresi olarak alır ve şekle geçirir. Avatarın yükleniyor durumu ise avatarın kendisine aittir.

```swift
// main.swift — renk semasi ortam, dolgu orani ebeveyn, yukleme durumu yerel
let storage: [String: Storage] = [
    "colorScheme": .environment,
    "fillRatio": .state(owner: "MeterScreen"),
    "isLoading": .state(owner: "AvatarImage"),
]

let screen = ViewTree(nodes: [
    ViewNode("MeterScreen", parent: nil, reads: ["fillRatio"]),
    ViewNode("MeterPanel", parent: "MeterScreen", reads: ["fillRatio"]),
    ViewNode("MeterShape", parent: "MeterPanel", reads: ["fillRatio"]),
    ViewNode("MeterIcon", parent: "MeterPanel", reads: ["colorScheme"]),
    ViewNode("AvatarImage", parent: "MeterPanel", reads: ["isLoading", "colorScheme"]),
], storage: storage)

let recomputes = [
    screen.change("renk-semasi-degisti", key: "colorScheme"),
    screen.change("doluluk-degisti", key: "fillRatio"),
    screen.change("yukleme-bitti", key: "isLoading"),
].flatMap { $0 }

countCauses(recomputes)
```

```
renk-semasi-degisti: colorScheme degisti | yeniden MeterIcon ortam, AvatarImage ortam | atlanan MeterScreen,MeterPanel,MeterShape
doluluk-degisti: fillRatio degisti | yeniden MeterScreen yerel, MeterPanel ebeveyn, MeterShape ebeveyn | atlanan MeterIcon,AvatarImage
yukleme-bitti: isLoading degisti | yeniden AvatarImage yerel | atlanan MeterScreen,MeterPanel,MeterShape,MeterIcon
yerel: 2
ebeveyn: 2
gozlem: 0
ortam: 2
```

`renk-semasi-degisti` satırında simge ve avatar ortam tetiğiyle yeniden hesaplandı; ekran, panel ve şekil atlandı. `doluluk-degisti` satırında değerin sahibi olan ekran yerel, panel ile şekil ebeveyn tetiğiyle yeniden hesaplandı. `yukleme-bitti` satırında yalnız avatar yerel tetikle yeniden hesaplandı: yükleniyor durumunu avatar kendi bünyesinde tutar.

Kaynakta karşılığı, uzak bir görseli yükleyen bir görünümdür. Yükleme sürerken bir yer tutucu, bittiğinde görselin kendisi gösterilir; durum değişince yalnız bu görünüm yeniden hesaplanır.

```swift
// Kaynak parca: uzak gorsel yuklenirken yer tutucu gosterir
import SwiftUI

struct AvatarImage: View {
    let url: URL?

    var body: some View {
        AsyncImage(url: url) { image in
            image.resizable()
        } placeholder: {
            ProgressView()
        }
    }
}
```

**GV21.** Bu ölçüm `colorScheme`, `fillRatio` ve `isLoading` için. Yükleme durumunun gerçekten görünümün kendi durumu olup olmadığı, yani çerçevenin bu durumu nerede sakladığı ölçülmedi; modelde avatar bunun sahibi sayıldı. Dolgu oranının sahibi olarak eklenen ekran da bir model varsayımıdır; kaynak parça yalnız panelin parametresini gösterir.

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

Statik bir görsel hiçbir değer okumaz. Bu yüzden hiçbir değişiklik onu yeniden hesaplatmaz. Aşağıdaki ağaçta logo görseli okuma kümesi boş bir yapraktır; panel kendi modunu, etiket ise panelin modunu okur.

```swift
// main.swift — statik gorsel hicbir deger okumaz
let storage: [String: Storage] = [
    "mode": .state(owner: "LogoPanel"),
]

let screen = ViewTree(nodes: [
    ViewNode("LogoPanel", parent: nil, reads: ["mode"]),
    ViewNode("StaticLogo", parent: "LogoPanel", reads: []),
    ViewNode("LogoCaption", parent: "LogoPanel", reads: ["mode"]),
], storage: storage)

let recomputes = [
    screen.change("mod-degisti", key: "mode"),
    screen.change("varlik-degisti", key: "logoAsset"),
].flatMap { $0 }

countCauses(recomputes)
```

```
mod-degisti: mode degisti | yeniden LogoPanel yerel, LogoCaption ebeveyn | atlanan StaticLogo
varlik-degisti: logoAsset degisti | yeniden yok | atlanan LogoPanel,StaticLogo,LogoCaption
yerel: 1
ebeveyn: 1
gozlem: 0
ortam: 0
```

`mod-degisti` satırında panel yerel, etiket ebeveyn tetiğiyle yeniden hesaplandı; logo atlandı. `varlik-degisti` satırında anahtarı okuyan görünüm olmadığı için hiçbir görünüm yeniden hesaplanmadı: üç görünüm de atlandı. Statik görsel, ağaçta bulunur ama hiçbir tetiğe duyarlı değildir; yeniden hesaplanması için bir değer okuması gerekir. Ebeveyninin onu yeniden kurmasının etkisi GV22'de ölçülmedi.

**GV22.** Bu ölçüm ebeveynin yeniden hesaplanmasının statik çocuğu yeniden kurmadığı varsayımına dayanır. Çerçevenin ebeveyn yeniden hesaplanınca çocuk görünümlerin gövdesini yeniden çalıştırıp çalıştırmadığı ölçülmedi.

## Özet

- Metin, simge, şekil ve görsel ağacın yapraklarıdır; her biri biçimini bir değerden alır.
- Renk şeması ortamdan okunur; okuyan simge ve avatar ortam tetiğiyle yeniden hesaplanır.
- Şeklin dolgu oranını veren ebeveyn durumu, şekil için ebeveyn tetiği üretir.
- Uzak görselin yükleniyor durumu görselin kendisine aittir ve yerel tetik üretir.
- Statik görsel hiçbir değer okumaz; hiçbir değişiklikte yeniden hesaplanmaz.
- Bu dersin tetiği: **ortam**.

## Sonraki Adım

Bu derste yapraklar değerlerini ortamdan, ebeveynden ve kendi bünyesinden aldı. Sıradaki derste ağacı kuran araca bakıyoruz: görünüm kurucu. Bir koşula bağlı içerik ya da bir kapanışla kurulan alt görünüm, hangi değere bağlıdır. Tetik bu kez ebeveyndir.
