Property Wrapper: temel kavramlar, sözdizimi ve SwiftUI'da örnekler

Yazar: IT Sectr Yayınlanma: 2026-06-19 Okuma süresi: 8 dk

Property Wrapper, kod tekrarı olmadan özelliklere erişim ve değişikliğe bir mantık katmanı ekleyen bir Swift mekanizmasıdır. SwiftUI'da Property Wrappers, görünüm durumu yönetiminin temeli haline geldi: @State, @Binding, @ObservedObject, @StateObject ve @Environment. Swift belgelerine (2025) göre, özellik sarmalayıcıları projelerdeki kalıp kodu ortalama %40 oranında azaltır. Property Wrapper'ı anlamak, her iOS geliştiricisinin framework ile etkili bir şekilde çalışması için gereklidir.

Önemli Noktalar

  • Property Wrapper — bir özelliğin getter ve setter'ına mantık ekleyen Swift sözdizimsel yapısı
  • @State — tek bir görünüme ait yerel durum için sarmalayıcı
  • @Binding — üst görünümden bir veri kaynağıyla çift yönlü bağlantı
  • @ObservedObject — sahiplik olmadan harici ObservableObject'i gözlemleme
  • @StateObject — mevcut görünüm düzeyinde ObservableObject oluşturma ve sahiplik

Property Wrapper nedir?

Property Wrapper — sürüm 5.1 ile tanıtılan, özellik erişim mantığını ayrı bir türde kapsüllemeye izin veren bir Swift dil yapısıdır. Her sınıfta tekrar tekrar getter ve setter yazmak yerine, geliştirici sarmalayıcıyı bir kez bildirir ve türün önünde @ ek açıklamasıyla uygular. Swift, özelliği otomatik olarak belirtilen türe sarar ve okuma ve yazma sırasında wrappedValue ve projectedValue yöntemlerini çağırır. Apple'a (WWDC 2019) göre, Property Wrappers SwiftUI için önemli bir soyutlama haline geldi.

Bir özellik sarmalayıcısı, @propertyWrapper özelliğine sahip bir yapı veya sınıftır. İçeride, böyle bir tür, gerçek değeri döndüren ve ayarlayan wrappedValue özelliğini uygulamalıdır. Swift derleyicisi, orijinal özelliğe erişimleri wrappedValue çağrılarıyla değiştirir ve uygulamayı çağıran koddan tamamen gizler. Ek olarak, $ sembolü aracılığıyla erişilebilen bir yansıtma olan projectedValue tanımlanabilir.

Property Wrappers'ın avantajı, mantığın yeniden kullanılabilirliğinde yatar. Örneğin, e-posta doğrulama, değer önbelleğe alma veya depolama senkronizasyonu için bir sarmalayıcı oluşturabilir — ve bunu projedeki herhangi bir özelliğe uygulayabilirsiniz. SwiftUI'da bu kavram her yerde kullanılır: her durum yönetimi mekanizması ayrı bir Property Wrapper olarak uygulanmıştır.

Swift'te Property Wrapper nasıl çalışır?

@WrapperType var value: T ek açıklamasıyla bir özellik bildirirken, Swift derleyicisi kodu dönüştürür. WrapperType'ın bir örneğini oluşturur ve wrappedValue aracılığıyla özelliğe erişim oluşturur. Kaynak kod let x = value, let x = _value.wrappedValue'ye dönüşür ve value = newValue, _value.wrappedValue = newValue'ye dönüşür. Bu dönüşüm derleme zamanında gerçekleşir ve çalışma zamanı ek yükü yoktur.

swift
@propertyWrapper
struct Capitalized {
    private var text: String

    var wrappedValue: String {
        get { text }
        set { text = newValue.capitalized }
    }

    init(initialValue: String) {
        text = initialValue.capitalized
    }
}

Listeleme, bir dizeyi otomatik olarak büyük harf biçimine dönüştüren Capitalized sarmalayıcısını gösterir. Bir değer atarken, setter kaydetmeden önce capitalized'i çağırır. Artık @Capitalized ek açıklamasına sahip herhangi bir özellik yalnızca doğru biçimlendirilmiş metni depolar. Bu yaklaşım, doğrulama ve biçimlendirme kodunun tekrarını tamamen ortadan kaldırır.

Yansıtma (projectedValue) — $ öneki aracılığıyla erişilebilen ek bir iletişim kanalıdır. SwiftUI'da bu özellik her yerde kullanılır: $state, Binding sağlar ve $observedObject, Published.Publisher döndürür. Yansıtma, sarmalayıcının değere temel erişimi değiştirmeden genişletilmiş bir arayüz sağlamasına izin verir.

SwiftUI'daki Temel Property Wrappers

SwiftUI, durum yönetimi için beş yerleşik Property Wrappers içerir: @State, @Binding, @ObservedObject, @StateObject ve @Environment. Her biri belirli bir görevi çözer ve farklı senaryolarda kullanılır. @State basit yerel veriler için, @Binding — alt görünümlere veri referansı iletmek için, @ObservedObject ve @StateObject — karmaşık nesneler için, @Environment — hiyerarşiden sistem değerleri için tasarlanmıştır.

SarmalayıcıAmaçSahiplik
@StateTek bir görünümün yerel durumuMevcut görünüm
@BindingEbeveyn ile çift yönlü bağlantıÜst görünüm
@ObservedObjectHarici nesne gözlemiHarici sahip
@StateObjectObservableObject oluşturmaMevcut görünüm
@EnvironmentHiyerarşiden sistem değerleriSwiftUI ortamı

Belirli bir Property Wrapper seçimi, veri kaynağına ve yaşam döngüsüne bağlıdır. Veriler tek bir görünüme aitse ve alt bileşenler tarafından ihtiyaç duyulmuyorsa — @State kullanın. Bir alt görünümün ebeveynin verilerini değiştirmesi gerekiyorsa — @Binding kullanın. Birden çok görünümde kullanılan nesneler için @ObservedObject ve @StateObject uygundur.

@State: görünümün yerel durumu

@State, tek bir görünüm içinde yerel durumu depolamak için bir Property Wrapper'dır. SwiftUI, @State özellikleri için belleği otomatik olarak yönetir ve her değişiklikte görünümü yeniden çizer. @State, yalnızca mevcut görünüme ait olan basit türler (String, Int, Bool, enum) ve yapılar için uygundur. Değer değiştiğinde, SwiftUI body özelliğini yeniden çalıştırır.

swift
struct CounterView: View {
    @State private var count: Int = 0

    var body: some View {
        VStack {
            Text("Sayım: \(count)")
            Button("Artır") {
                count += 1
            }
        }
    }
}

Örnekte, @State özelliği count sayacın mevcut değerini depolar. SwiftUI bu özellik için yığında bir depolama alanı oluşturur ve bunu CounterView'ın yaşam döngüsüne bağlar. Düğmeye basıldığında, count 1 artar, SwiftUI değişikliği algılar ve body'yi yeniden çalıştırarak yeni değeri gösterir. Önemli: @State karmaşık referans türleri için kullanılmamalıdır — bunun için @StateObject ve @ObservedObject vardır.

@Binding: görünümler arasında çift yönlü bağlantı

@Binding, başka bir görünüme ait bir veri kaynağına referans oluşturur. Binding kendi başına bir değer depolamaz — verileri @State, @StateObject veya ebeveynden iletilen başka bir Binding aracılığıyla okur ve yazar. Bu, alt bileşenlerin verilere doğrudan sahip olmadan ve geri aramalar olmadan ata durumunu değiştirmesine olanak tanır.

swift
struct ToggleSwitch: View {
    @Binding var isOn: Bool

    var body: some View {
        Toggle("Switch", isOn: $isOn)
    }
}

Listelemede, ToggleSwitch üst görünümden @BindingBool alır. Ebeveyn, @State var isToggleOn = false oluşturur ve $isToggleOn'u ToggleSwitch'in başlatıcısına iletir. Kullanıcı alt görünüm içindeki anahtarı değiştirdiğinde, değişiklik anında ebeveynin @State'ine yansır. Binding mekanizması, hiyerarşide yukarı doğru değişiklikleri iletmek için delegelere veya closure'lara olan ihtiyacı tamamen ortadan kaldırır.

@ObservedObject ve @StateObject: harici veri

@ObservedObject, dışarıdan iletilen bir ObservableObject örneğini gözlemlemek için bir Property Wrapper'dır. Görünüm bu nesneye sahip değildir — üst bileşende oluşturulur veya Environment aracılığıyla enjekte edilir. ObservableObject içindeki herhangi bir @Published özelliği değiştiğinde, SwiftUI @ObservedObject aracılığıyla abone olan tüm görünümleri yeniden çizer.

@StateObject — doğrudan görünümde ObservableObject oluşturmak ve sahiplenmek için bir sarmalayıcıdır. @ObservedObject'in aksine, @StateObject, görünümün tüm yaşam döngüsü boyunca nesnenin tek bir örneğini garanti eder. SwiftUI görünüm yapısını yeniden oluştursa bile (ki bu sık sık olur), @StateObject mevcut nesneyi korur ve başlatıcıyı yeniden çağırmaz.

swift
class UserSettings: ObservableObject {
    @Published var username: String = "Guest"
}

struct ProfileView: View {
    @StateObject var settings = UserSettings()

    var body: some View {
        ChildProfileView(settings: settings)
    }
}

struct ChildProfileView: View {
    @ObservedObject var settings: UserSettings

    var body: some View {
        Text("Merhaba, \(settings.username)")
    }
}

Örnekte, ProfileView @StateObject aracılığıyla UserSettings oluşturur ve nesnenin sahibi olur. ChildProfileView aynı örneği @ObservedObject aracılığıyla alır — gözlemler ancak yaşam döngüsünü yönetmez. username değiştiğinde, her iki görünüm de güncellenir. ChildProfileView @ObservedObject yerine @StateObject kullanmış olsaydı, her işlemede başlangıç değeriyle yeni bir örnek oluşturulurdu.

Ana kural: @StateObject, nesneyi oluşturan görünümde (gerçeğin kaynağı) kullanılırken, @ObservedObject, ebeveynden zaten oluşturulmuş bir nesneyi alan görünümde kullanılır. Bu kuralın ihlali, durum kaybına veya beklenmeyen veri yeniden oluşturulmasına yol açar.

Özel Property Wrapper oluşturma

Swift, herhangi bir tekrarlayan özellik erişim mantığı için özel Property Wrappers oluşturulmasına izin verir. Sadece @propertyWrapper özelliğine sahip bir yapı veya sınıf bildirin ve wrappedValue'yi uygulayın. Aşağıda, değeri otomatik olarak UserDefaults ile senkronize eden UserDefaultsWrapper sarmalayıcısı gösterilmektedir.

swift
@propertyWrapper
struct UserDefaultsWrapper<T> {
    let key: String
    let defaultValue: T

    var wrappedValue: T {
        get { UserDefaults.standard.object(forKey: key) as? T ?? defaultValue }
        set { UserDefaults.standard.set(newValue, forKey: key) }
    }
}

struct AppConfig {
    @UserDefaultsWrapper(key: "theme", defaultValue: "light")
    var theme: String
}

UserDefaultsWrapper sarmalayıcısı, UserDefaults tarafından desteklenen herhangi bir veri türüyle çalışmak için genel bir T kullanır. Getter, değeri anahtarla okur, setter yazar. theme özelliğine @UserDefaultsWrapper(key:defaultValue:) uygulamak, onu otomatik olarak depolamaya bağlar — tüm UserDefaults mantığı sarmalayıcının içinde gizlidir. Bu, Property Wrappers ile kalıp kodun azaltılmasının tipik bir örneğidir.

Özel sarmalayıcılar oluştururken, performansı dikkate almak önemlidir. Getter ve setter özelliğe her erişimde çağrıldığından, wrappedValue'ya ağır G/Ç işlemleri yerleştirilmemelidir. Zaman uyumsuz veri depolama için, Property Wrappers'ı ObservableObject ve @Published ile birleştirmek daha iyidir.

Sıkça Sorulan Sorular

@State ve @StateObject arasındaki fark nedir?

@State basit türler (String, Int, Bool) ve yapılar için tasarlanmışken, @StateObject ObservableObject uygulayan referans türleri içindir. @State değeri doğrudan SwiftUI'da depolar, @StateObject yığında bir sınıf örneğini yönetir.

@Binding @State olmadan kullanılabilir mi?

Evet, @Binding @StateObject, @ObservedObject veya $ yansıtması kullanılarak başka bir Binding'den oluşturulabilir. Binding ayrıca ObservableObject'ten $object.$publishedProperty aracılığıyla veya InlineBinding'den Binding.constant(value) aracılığıyla başlatılabilir.

Tüm uygulamada kullanılan veriler için hangi Property Wrapper seçilmelidir?

Global veriler için @EnvironmentObject kullanın veya ObservableObject'i EnvironmentValues aracılığıyla enjekte edin. @StateObject, kök görünüm için uygundur ve ardından @ObservedObject aracılığıyla alt bileşenlere iletilir.

@ObservedObject neden verileri yeniden oluşturabilir?

@ObservedObject nesneye sahip değildir — üst görünüm yeniden oluşturulur ve yeni bir örnek iletirse, @ObservedObject ona geçer. Durum kaybını önlemek için, sahip olan görünüm @StateObject kullanmalıdır.

Zaman uyumsuz işlemler için Property Wrapper oluşturulabilir mi?

Evet, ancak sınıf içinde @Published ve async işlevleriyle ObservableObject kombinasyonunu kullanmak daha kolaydır. Property Wrapper doğası gereği senkronizedir — wrappedValue her erişimde hesaplanır, bu da uzun süren işlemler için uygun değildir.

Özet

  • Property Wrapper — kod tekrarı olmadan özellik erişim mantığını kapsüllemek için Swift 5.1 sözdizimsel yapısı
  • @State — basit türler için yerel durum, değişiklikte görünümü otomatik olarak yeniden çizer
  • @Binding — sahiplik olmadan üst görünüm verilerine referans, $ yansıtmasıyla erişilebilir
  • @StateObject — yaşam döngüsü başına tek örnek garantisi ile ObservableObject sahipliği
  • @ObservedObject — üst bileşenden iletilen ObservableObject gözlemi
  • @Environment — SwiftUI sistem ortamı nesnelerine erişim
  • Özel sarmalayıcılar @propertyWrapper özelliği ve wrappedValue uygulamasıyla oluşturulur

Anahtar teslim bir mobil uygulama geliştireceğiz

IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.

Projeyi tartış

Ayrıca okuyun