Etkileşimli SwiftUI önizlemeleri oluşturmak için her önizlemeye kendi yerel durumunu verin, düzenleyiciye gözlemlenebilir bir görünüm modeli aktarın ve düzenlenebilir özellikleri bağlamalar aracılığıyla açığa çıkarın. Bu adım adım kılavuzda, sentetik örnek metinler kullanan küçük bir macOS etiket düzenleyicisi oluşturuluyor.

Önizleme durumunun nerede bulunacağını seçin

Amaç, bir kullanıcının etiketin başlığını ve ayrıntı metnini değiştirdiği, ardından ayrıntının gösterilip gösterilmeyeceğini belirlediği bir masaüstü düzenleyiciyi önizlemektir. Düzenleyici değişikliklere hemen yanıt vermeli ve her önizleme açıkça belirtilmiş bir örnek yapılandırmayla başlamalıdır.

Etkileşimi destekleyen en küçük girişi kullanın. Apple, karmaşık bağımlılıkların önizlemeleri oluşturmayı zorlaştırması nedeniyle görünümlere yalnızca ihtiyaç duydukları verilerin aktarılmasını önerir. Statik bir etiket metin dizgesi alabilir; bir düzenleyici ise durumuna yazılabilir bir bağlantı gerektirir. Arayüz dosyalarınıza önizlemeler ekleme.

Görünümün ihtiyacı Uygun girdi Örnek durumun yeri
Sabit metin görüntülemek Değişmez bir metin dizgesi Doğrudan önizlemede
Üst öğesinin sahip olduğu tek bir değeri düzenlemek Bir @Binding özelliği Önizleme barındırıcısında yerel @State
Birbiriyle ilişkili birkaç gözlemlenebilir özelliği düzenlemek @Bindable aracılığıyla sunulan gözlemlenebilir bir model Önizleme barındırıcısının @State’inde saklanan bir model örneği
Ortam üzerinden sağlanan bir modeli okumak Bir ortam bağımlılığı Önizlemenin kökünde açıkça ekleme

Bu örnekte görünüm modeli iki metin dizgesi, bir görünürlük ayarı ve hesaplanan bir görüntüleme başlığı içeriyor. Her önizleme ayrı bir örneğe sahip. Böylece başlangıç koşulları önizleme bildiriminin yanında görünür oluyor ve örneğin paylaşılan, değiştirilebilir bir tekil nesneye bağımlı olması önleniyor.

macOS SwiftUI hedefi hazırlama

Burada gösterilen satır içi @Previewable sözdizimi için Xcode 16 veya daha yenisini kullanın. Apple bu makroyu Xcode 16’da kullanıma sundu. Bu örneğin dağıtım hedefini, SwiftUI’nin Observation’ı desteklediği macOS 14 veya daha yenisi olarak ayarlayın; Apple’ın güncel Previewable() başvurusu da macOS 14 kullanılabilirliğini listeliyor. Xcode 16 Sürüm Notları, Uygulamanızdaki model verilerini yönetme, Previewable().

Mevcut bir macOS SwiftUI uygulama hedefine LabelEditor.swift adlı bir Swift dosyası ekleyin. Sonraki iki kod bloğu birlikte eksiksiz bir önizleme örneği oluşturuyor. Uygulamanın mevcut giriş noktasını koruyun; bu dosyada model, düzenleyici ve önizlemeler tanımlanıyor.

Kod, desteklenen araç zincirlerinde @State yazımını kullanıyor. Apple’ın güncel belgeleri uygulama ayrıntısını açıklıyor: Xcode 26 ve önceki sürümlerde State özellik sarmalayıcısı, Xcode 27 ve sonraki sürümlerde ise State() makrosu kullanılıyor. Oluşturulan kodu incelerken veya başlatma maliyetlerini değerlendirirken bu ayrımı göz önünde bulundurun. State, State().

Gözlemlenebilir modeli ve düzenlenebilir görünümü oluşturma

Arayüzün okuduğu özellikleri SwiftUI’nin izleyebilmesi için modele @Observable uygulayın. Metin alanları ve açma/kapama düğmesinin ihtiyaç duyduğu özellik bağlamalarını oluşturmak için düzenleyicide @Bindable kullanın. Apple, gözlemlenebilir modelleri düzenlemek için bu bileşimi belgeliyor. Uygulamanızdaki model verilerini yönetme, Bindable.

import Foundation
import Observation
import SwiftUI

@MainActor
@Observable
final class LabelViewModel {
    var title: String
    var detail: String
    var showsDetail: Bool

    init(
        title: String,
        detail: String,
        showsDetail: Bool = true
    ) {
        self.title = title
        self.detail = detail
        self.showsDetail = showsDetail
    }

    var displayedTitle: String {
        let trimmed = title.trimmingCharacters(
            in: .whitespacesAndNewlines
        )
        return trimmed.isEmpty ? "Untitled label" : trimmed
    }
}

@MainActor
struct LabelEditor: View {
    @Bindable var model: LabelViewModel

    var body: some View {
        VStack(alignment: .leading, spacing: 16) {
            VStack(alignment: .leading, spacing: 6) {
                Text("Title")
                TextField("Label title", text: $model.title)
            }

            VStack(alignment: .leading, spacing: 6) {
                Text("Detail")
                TextField("Label detail", text: $model.detail)
            }

            Toggle("Show detail", isOn: $model.showsDetail)

            Divider()

            Text("Rendered label")
                .font(.caption)
                .foregroundStyle(.secondary)

            VStack(alignment: .leading, spacing: 8) {
                Text(model.displayedTitle)
                    .font(.title2)
                    .fixedSize(horizontal: false, vertical: true)

                if model.showsDetail {
                    Text(model.detail)
                        .foregroundStyle(.secondary)
                        .fixedSize(horizontal: false, vertical: true)
                }
            }
            .frame(maxWidth: .infinity, alignment: .leading)
            .padding()
            .background(
                .quaternary,
                in: RoundedRectangle(cornerRadius: 10)
            )
        }
        .textFieldStyle(.roundedBorder)
        .padding(20)
    }
}

Model, tüm örnek değerleri başlatıcısı aracılığıyla bilerek alıyor. Başlatıcısı yalnızca yerel özelliklere atama yapıyor. Geri dönüş hesabı, kullanıcının girdiği başlığı üzerine yazmadan etiketin görüntülenen metnini değiştiriyor: yalnızca boşluklardan oluşan bir başlık düzenlenebilir kalırken, görüntülenen sonuç Untitled label oluyor.

Düzenleyici modelini çağıran taraftan alıyor. @Bindable bildirimi $model.title gibi bağlamalar sağlıyor; durumun sahipliği önizleme barındırıcısında olacak. Bu görünüm yalnızca model değerlerini görüntülüyor olsaydı, gözlem için düz bir model başvurusu yeterli olurdu. Denetimler yazılabilir özellik bağlamaları gerektirdiğinden Bindable saklaması burada işe yarıyor. Bindable.

Her önizlemeye bağımsız örnek durumu verme

Aşağıdaki bildirimleri aynı dosyanın sonuna ekleyin. Her biri açıkça belirtilmiş sentetik değerlerle kendi modelini oluşturuyor. Genişlikler örnek amaçlı düzen denetimleridir; önerilen en küçük pencere boyutları değildir.

#Preview("Standard label") {
    @Previewable @State var model = LabelViewModel(
        title: "Sample tile",
        detail: "Blue square, medium size"
    )

    LabelEditor(model: model)
        .frame(width: 420)
        .preferredColorScheme(.light)
}

#Preview("Long label in a narrow editor") {
    @Previewable @State var model = LabelViewModel(
        title: "Sample collection with a longer descriptive label",
        detail: "Round tiles arranged in three columns"
    )

    LabelEditor(model: model)
        .frame(width: 300)
        .preferredColorScheme(.dark)
}

#Preview("Blank title and hidden detail") {
    @Previewable @State var model = LabelViewModel(
        title: "   ",
        detail: "An optional detail line",
        showsDetail: false
    )

    LabelEditor(model: model)
        .frame(width: 420)
}

@Previewable, yerel durum bildirimini #Preview tarafından oluşturulan gömülü bir SwiftUI görünümünün parçası yapar. Apple, etiketlenen bildirimlerin oluşturulan bu görünümde özelliklere dönüştüğünü belgeliyor. Bildirimi önizleme kapanışının köküne yerleştirin; @Previewable’ı önizleme gövdesinin dışında kullanmak hatadır. Previewable().

Ortaya çıkan sahiplik zinciri açıktır: oluşturulan önizleme barındırıcısı modeli @State içinde saklar, LabelEditor model başvurusunu alır ve @Bindable düzenlenebilir özellikleri sunar. SwiftUI, Observation modelinin durumda saklanmasını ve bu başvurunun alt görünümlere aktarılmasını destekler. State.

Başlatıcı değerlerini başlangıç örnekleri olarak değerlendirin. Etkileşimli bir önizleme çalışırken bu değerleri değiştirebilir. Belirli bir düzeni yeniden oluştururken başlangıç görünümünü karşılaştırmadan önce yeni bir önizleme örneğine dönün.

Davranışı küçük bir senaryo matrisiyle denetleme

LabelEditor.swift dosyasını açın, Show Canvas’ı seçin ve tuval sekmelerinden adlandırılmış bir önizleme belirleyin. Tuval duraklatılmışsa Restart’ı kullanın. Metin girişini ve denetim mantığını denemek için Live modunu etkinleştirin. Bu denetimler Apple’ın güncel tuval kılavuzunda açıklanıyor. Tuvalde önizlemelerle etkileşim kurma.

Durum sorunlarını düzen sorunlarından ayırmak için aşağıdaki denetimleri kullanın. Beklenen sonuçlar örnek koddan çıkarılmıştır; test sonucu olarak raporlanmamıştır.

Senaryo Eylem Beklenen sonuç
Standart etiket Başlığı Amber circle olarak değiştirin Görüntülenen başlık hemen değişir
Ayrıntı görünürlüğü Show detail seçeneğini kapatıp yeniden açın Ayrıntı kaybolur ve metni korunarak geri gelir
Boş başlık Başlıktaki tüm karakterleri silin Görüntülenen başlık Untitled label olur
Boşluklardan oluşan başlık Yalnızca boşluk girin Alan bu boşlukları korur; görüntülenen başlık geri dönüş değerini kullanır
Dar düzenleyici Uzun başlık önizlemesini inceleyin Görüntülenen başlık kartın içinde satırlara bölünür
Ayrı örnekler Bir önizlemeyi düzenleyin, ardından yeni ve farklı bir önizlemeyi inceleyin Diğer önizleme, bildiriminde belirtilen kendi model değerleriyle başlar

Metin girişi çalışıyor ancak görüntülenen çıktı değişmiyorsa alan bağlamasıyla çıktının okuduğu özellik arasındaki bağlantıyı inceleyin. Burada her iki yol da doğrudan veya displayedTitle üzerinden model.title’e ulaşıyor. Görünürlüğü değiştirmek ayrıntıyı temizliyorsa boş değer atayan kodu arayın; bu örnek yalnızca showsDetail’i değiştiriyor.

Araştırma ortamında Swift derleyicisi veya macOS önizleme çalışma zamanı mevcut değildi; bu nedenle örnekler derlenip çalıştırılmak yerine belgelenmiş API’lere göre incelendi. Düzenleyiciyi uyarlamadan önce hedefi derleyin ve etkileşim denetimlerini Xcode’da tamamlayın.

Paylaşılan kurulumu düzenlenebilir örneklerden ayrı tutma

Bu kadar küçük bir model için yerel oluşturma, her önizlemenin anlaşılmasını kolaylaştırıyor. Birden çok önizleme sonunda maliyetli ve yeniden kullanılabilir bir kuruluma ihtiyaç duyarsa Apple, paylaşılan bağlamı önbelleğe alıp katılan önizlemelerde yeniden kullanan PreviewModifier sunuyor. API için macOS 15 veya daha yenisi gerekiyor. PreviewModifier.

Belgelenen bu paylaşım davranışı pratik bir tasarım tercihi doğuruyor: bağımsız olarak düzenlenebilir örnek modelleri yerel tutun; paylaşılan bağlamı ise yalnızca katılan önizlemelerin yeniden kullanmasını istediğiniz kurulum için ayırın. Paylaşılan ve değiştirilebilir bir modelde yapılan düzenlemeler de paylaşılır; bu da ayrı senaryoları karşılaştırmayı zorlaştırabilir.

Mevcut bir görünüm modelini türe göre ortamdan alıyorsa gereken örneği önizlemenin köküne ekleyin. Apple, istenen türde zorunlu bir model bulunmadığında istisna oluştuğunu belgeliyor. Bu nedenle bir önizlemenin, seçilen kökün gerçekten okuduğu bağımlılıkları sağlaması gerekir. Uygulamanızdaki model verilerini yönetme.

AppKit ve TextKit sınırlarını koruma

Yukarıdaki düzenleyici SwiftUI denetimlerini kullanıyor. Mevcut macOS düzenleyiciniz bir AppKit metin görünümü içeriyorsa bu görünümü SwiftUI hiyerarşisine eklemek için NSViewRepresentable kullanın. Görünümü makeNSView aracılığıyla oluşturup yapılandırın, ardından gelen SwiftUI durumunu updateNSView aracılığıyla uygulayın. Düzenlemelerin SwiftUI’ye geri iletilmesi gerektiğinde AppKit temsilcisi değişikliklerini bir koordinatör aracılığıyla aktarın. Temsil edilen görünümün çerçevesini ve sınırlarını SwiftUI’nin denetlemesine izin verin. NSViewRepresentable.

Apple ayrıca AppKit görünümlerinin ve görünüm denetleyicilerinin doğrudan önizlenmesini destekliyor. Ancak @Previewable yalnızca SwiftUI’ye özgüdür ve doğrudan AppKit önizlemelerinde kullanılamaz. Bu makaledeki yerel durum düzenini AppKit içeriğiyle kullanmak için temsil edilebilir görünümü içeren bir SwiftUI barındırıcısını önizleyin. Arayüz dosyalarınıza önizlemeler ekleme.

Bir NSTextView oluştururken metin altyapısı seçiminizi koruyun. Apple, başlatma sırasında TextKit 2’yi seçmek için NSTextView(usingTextLayoutManager: true) kullanıldığını belgeliyor. TextKit kılavuzu, TextKit 1’e ait layoutManager özelliğine erişmenin söz konusu metin görünümü örneği için tek yönlü bir geri dönüşü tetikleyebileceğini de açıklıyor. Tercih ettiğiniz altyapı TextKit 2 ise uygun TextKit 2 API’lerini kullanın; önizleme bu sınırları ortadan kaldırmaz. TextKit ve metin görünümlerindeki yenilikler.

Önizleme hatalarını sahiplik sınırında teşhis etme

İlk derleme tanısından başlayın. Swift makroları derleme zamanında kod oluşturduğundan, makro çağrısında vurgulanan bir hata oluşturulan bildirimlerle ilgili olabilir. Bu kodu incelemek için Xcode’daki Editor > Expand Macro komutunu kullanın. Makroları uygulama.

Ardından durum mekanizmasını denetleyin. Mevcut Combine tabanlı bir ObservableObject, uygun sahiplik düzenini gerektirir: Apple, böyle bir nesneyi State içinde saklamanın yayımlanmış özelliklerindeki değişiklikleri izlemediği konusunda uyarıyor ve sahipler için StateObject kullanımını öneriyor. Buradaki örnek @Observable kullanıyor; bu nedenle durum sahipliği Observation yolunu izliyor. State.

Tamamlanmış önizleme dosyasını açık başlangıç değerleri ve görünür etkileşimler etrafında düzenleyin. Standart, uzun başlık ve boş başlık senaryoları beklendiği gibi çalıştığında aynı düzenleyiciyi uygulamanızın uygun üst görünümünün sahip olduğu bir modelle yeniden kullanın. Önizleme örnekleri, bu arayüz koşullarını yeniden oluşturmanın kısa bir yolunu sunar.

Kaynaklar