Ders 04 / 21
Düzen Sistemi
Önerilen boyutu belirleyen ebeveyn değerinin çocuklara ebeveyn tetiği olarak indiğinin, yazı boyutu tercihinin ortamdan okunduğunun ve boyut önerisinin ölçülen bir değer olmadığının ölçümü.
Yayın Güncelleme
Bu derste
- Düzen sisteminin üç adımını (öneri, seçim, yerleştirme) kaynak parçada okur
- Önerilen boyutu belirleyen ebeveyn değerinin çocuklara ebeveyn tetiği olarak indiğini ölçer
- Yazı boyutu tercihi gibi ortam değerinin ayrı bir tetik ürettiğini gösterir
- Boyut önerisinin ölçülen bir durum değeri olmadığını ve modelin onu ölçüm dışı bıraktığını ölçer
İçindekiler
Önceki derste yığıtın aralık ve ekseni, sahibi olan ebeveynden çocuklara indi. Bu derste aynı inişi boyutlar için izliyoruz. Düzen sisteminde üst görünüm, çocuğuna ne kadar yer önerdiğini söyler; çocuk bu öneriden kendi boyutunu seçer; üst görünüm de çocuğu seçtiği boyutla yerleştirir. Önerinin kendisi bir ebeveyn kararıdır, ama bu kararı belirleyen bir değer çoğu zaman ebeveynin durumunda durur. Soru aynı kalır: bu yeniden hesaplamayı ne tetikledi? Bu derste bakılan tetik, ebeveyn.
// 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 özet panelidir: panelin kendisi, bir başlık, bir grafik ve bir not.
Öneri, Seçim, Yerleştirme
Düzen üç adımda ilerler. Ebeveyn çocuğa bir boyut önerir; çocuk bu öneriyi kendi içeriğine göre yorumlayıp bir boyut seçer; ebeveyn de çocuğu seçilen boyutla kendi alanında bir yere koyar. Çocuk öneriyi kabul edebilir, küçük kalabilir ya da öneriden büyük bir boyut isteyebilir. Aşağıdaki parça adımları kaynak olarak gösterir.
// Kaynak parca: oneri, secim ve yerlestirme
import SwiftUI
struct SummaryPanel: View {
@State private var isCompact = false
var body: some View {
VStack {
Text("Ozet")
.layoutPriority(isCompact ? 0 : 1)
Rectangle()
.frame(maxWidth: .infinity, minHeight: isCompact ? 40 : 120)
Text("Not")
.lineLimit(2)
}
}
}
isCompact panelin kendi durumudur ve iki yerde yer önerisini etkiler: başlığın düzen önceliği ile grafiğin asgari yüksekliği. Notun satır sınırı sabittir. layoutPriority ise yer daraldığında hangi çocuğun önce yer alacağını söyler; yüksek öncelikli çocuk önce boyutunu seçer, kalan yer öteki çocuklara bölüşülür. Bu parça KAYNAK’tır ve boyutların sayı olarak ne çıktığı bu derste ölçülmedi.
GV11. Bu ölçüm düzenin üç adımını anlatır ama boyut hesabı yapmaz. Önerilen boyutun hangi sayıya dönüştüğü, layoutPriority değerlerinin bölüşümü ve seçilen boyutların yerleştirmesi ölçülmedi.
Önerinin Dayandığı Değer
Öneriyi belirleyen değer ebeveynin durumundaysa, çocuğun bunu okuması ebeveyn tetiği üretir. Aşağıdaki ağaçta isCompact ve density panelin değerleridir; başlık ve grafik bunları okur. Yazı boyutu tercihi (dynamicTypeSize) ise ortamdan gelir ve başlık ile notun yer ihtiyacını etkiler.
// main.swift — onerilen boyutu belirleyen deger ebeveyn, yazi boyutu ortam
let storage: [String: Storage] = [
"isCompact": .state(owner: "SummaryPanel"),
"density": .state(owner: "SummaryPanel"),
"dynamicTypeSize": .environment,
]
let screen = ViewTree(nodes: [
ViewNode("SummaryPanel", parent: nil, reads: ["isCompact", "density"]),
ViewNode("SummaryTitle", parent: "SummaryPanel", reads: ["isCompact", "dynamicTypeSize"]),
ViewNode("SummaryChart", parent: "SummaryPanel", reads: ["isCompact", "density"]),
ViewNode("SummaryNote", parent: "SummaryPanel", reads: ["dynamicTypeSize"]),
], storage: storage)
let recomputes = [
screen.change("kompakt-oldu", key: "isCompact"),
screen.change("yogunluk-degisti", key: "density"),
screen.change("yazi-boyutu-degisti", key: "dynamicTypeSize"),
].flatMap { $0 }
countCauses(recomputes)
kompakt-oldu: isCompact degisti | yeniden SummaryPanel yerel, SummaryTitle ebeveyn, SummaryChart ebeveyn | atlanan SummaryNote yogunluk-degisti: density degisti | yeniden SummaryPanel yerel, SummaryChart ebeveyn | atlanan SummaryTitle,SummaryNote yazi-boyutu-degisti: dynamicTypeSize degisti | yeniden SummaryTitle ortam, SummaryNote ortam | atlanan SummaryPanel,SummaryChart yerel: 2 ebeveyn: 3 gozlem: 0 ortam: 2
kompakt-oldu satırında panel yerel, başlık ve grafik ebeveyn tetiğiyle yeniden hesaplandı; not atlandı. yogunluk-degisti satırında yalnız grafik okuduğu için panel yerel, grafik ebeveyn. yazi-boyutu-degisti satırında panel ve grafik atlandı, başlık ile not ortam tetiğiyle yeniden hesaplandı. Yazı boyutu tercihini kullanıcı sistem ayarından değiştirir; hiçbir ebeveynin durumu bu değerin sahibi değildir.
Notun isCompact değerini okumaması kaynak parçayla uyumludur: satır sınırı sabit bir sayıdır. Okuma kümesi kaynak parçanın okumasından türetilir; kaynakta bulunmayan okuma varsayımdır ve GV12’de belirtilir; not yalnız yazı boyutuna bağlı kaldığı için kompakt-oldu satırında atlanır.
GV12. Bu ölçüm isCompact, density ve dynamicTypeSize için. Kaynak parçada görünmeyen density değerinin panelin durumu olduğu ve yalnız grafiğin onu okuduğu varsayıldı; bu bir ölçüm kuralı değil, ağaç tanımıdır.
Sınırlayıcı Ölçüm
Önerilen boyut bir durum değeri değildir. Ebeveyn ile çocuk arasındaki bir görüşmedir: ebeveyn önerir, çocuk seçer ve sonuç yerleşimde ortaya çıkar. Modelde bu görüşmenin bir anahtarı yoktur. Grafik proposedWidth değerini okuyor gibi yazılsa bile, model bunu saklama tablosunda bulamaz ve tetiği ölçüm dışı sayar.
// main.swift — onerilen genislik tabloda yoksa tetik olcum disidir
let storage: [String: Storage] = [
"isCompact": .state(owner: "SummaryPanel"),
]
let screen = ViewTree(nodes: [
ViewNode("SummaryPanel", parent: nil, reads: ["isCompact"]),
ViewNode("SummaryChart", parent: "SummaryPanel", reads: ["isCompact", "proposedWidth"]),
ViewNode("SummaryNote", parent: "SummaryPanel", reads: []),
], storage: storage)
let recomputes = [
screen.change("genislik-onerildi", key: "proposedWidth"),
screen.change("kompakt-oldu", key: "isCompact"),
].flatMap { $0 }
countCauses(recomputes)
genislik-onerildi: proposedWidth degisti | yeniden SummaryChart olcum-disi | atlanan SummaryPanel,SummaryNote kompakt-oldu: isCompact degisti | yeniden SummaryPanel yerel, SummaryChart ebeveyn | atlanan SummaryNote yerel: 1 ebeveyn: 1 gozlem: 0 ortam: 0
genislik-onerildi satırı çekirdeğin ölçemediği satırdır: grafik değeri okuduğu için listelenir, ama satır olcum-disi yazar ve bir yeniden hesaplama iddiası değildir; sayaç da onu göstermez. Model burada bir hesap yapmaz: önerilen genişliğin sayı olarak ne olduğunu, grafiğin ne seçtiğini ya da paneldeki yerleşimi bilmez. Yalnız hangi görünümün hangi anahtarı okuduğunu ve anahtarın tabloda olup olmadığını söyler. kompakt-oldu satırı ise tabloda olan değer için sonucun nasıl değiştiğini gösterir.
GV13. Bu ölçüm boyut görüşmesini tek bir anahtara indirger ve o anahtarın tabloda olmadığı durumu inceler. Gerçek bir boyut değişiminin hangi görünümleri yeniden hesaplattığı, çerçevenin yerleşim geçişleri ve çocuğun öneriye verdiği yanıt ölçülmedi.
Özet
- Düzen üç adımdır: ebeveyn önerir, çocuk boyutunu seçer, ebeveyn çocuğu yerleştirir.
- Önerilen boyutu belirleyen değer ebeveynin durumundaysa, onu okuyan çocuk ebeveyn tetiğiyle yeniden hesaplanır.
- Yazı boyutu tercihi ortamdan gelir ve ortam tetiği üretir.
layoutPriorityyer daraldığında kimin önce boyut seçeceğini belirler; sayısal bölüşümü bu derste ölçülmedi.- Önerilen boyut bir durum değeri değildir; modelde anahtarı yoksa tetik ölçüm dışı sınıflanır.
- Bu dersin tetiği: ebeveyn.
Sonraki Adım
Bu derste ebeveyn değeri, çocuğa önerilen boyutun dayanağıydı. Sıradaki derste aynı soruyu ızgara için soruyoruz: bir ızgaranın kaç sütun gösterdiğini ne belirler. Cevabın bir kısmı ortamdan gelen bir boyut sınıfıdır; bu yüzden tetik de ortam olacaktır.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.