1. Giriş
Swift’te access control (erişim kontrolü), kodun farklı bölümlerinin birbirinden nasıl izole edildiğini belirler.private(set) ise bu erişim kontrol mekanizmalarının çok kullanışlı ama bazen gözden kaçan bir üyesidir.
Temel olarak:
- Dışarıdan (
external) sadece okunabilir - İçeriden (
internal) hem okunabilir hem yazılabilir
private(set) var propertyName: PropertyType
Yani, getter herkese açık (
internalvarsayılan) olurken, setter yalnızca tanımlandığı erişim seviyesinde (ör.private) görünür.
2. Neden Kullanılır?
private(set) kullanmanın en büyük faydası encapsulation’dır (kapsülleme).
Bir değişkenin değerini dış dünyaya göstermek isteriz ama değiştirilmesini istemeyiz. Bu, özellikle state management veya immutable interface tasarımlarında önemlidir.
3. Temel Örnek
Örnek 1 — Sayaç
class Counter {
private(set) var count = 0
func increment() {
count += 1
}
}
let counter = Counter()
print(counter.count) // 0 — Okuyabiliriz
counter.increment()
print(counter.count) // 1
// counter.count = 10 ❌ HATA: 'count' setter is inaccessible
Burada count değeri dışarıdan değiştirilemez ama okunabilir.
Sadece Counter sınıfının içinden güncellenebilir.
4. Stored Property ve Computed Property Farkı
4.1 Stored Property (Depolanan Özellik)
- Bellekte fiziksel olarak değer saklar.
private(set)eklediğinde setter erişim kontrolüne girer.willSetvedidSetgibi property observer’lar kullanılabilir.
struct Player {
private(set) var score = 0
mutating func add(points: Int) {
score += points
}
}
4.2 Computed Property (Hesaplanan Özellik)
- Değer fiziksel olarak saklanmaz, her erişimde hesaplanır.
private(set)burada setter metodunu sınırlamak anlamına gelir, ama computed property’nin setter’ı varsa.
struct Rectangle {
var width: Double
var height: Double
private(set) var area: Double {
get { width * height }
set { width = sqrt(newValue); height = sqrt(newValue) } // setter sınırlı
}
}
📌 Fark: Stored property’de değer saklanır, computed property’de saklanmaz; private(set) sadece setter erişim seviyesini kısıtlar, stored/computed ayrımı bu mantığı değiştirmez.
Ama stored property’de direkt bir “value” vardır, computed’da “hesaplama” vardır.
5. İleri Düzey Kullanımlar
Örnek 2 — State Yönetimi
class ViewModel {
private(set) var isLoading = false
func loadData() {
isLoading = true
// API isteği...
isLoading = false
}
}
Burada UI tarafı isLoading değerini gözlemleyebilir, ama değiştiremez.
Bu, View → ViewModel bağımlılığını güvenli hale getirir.
Örnek 3 — Koleksiyon Yönetimi
struct ShoppingCart {
private(set) var items: [String] = []
mutating func addItem(_ item: String) {
items.append(item)
}
}
var cart = ShoppingCart()
cart.addItem("Elma")
print(cart.items) // ["Elma"]
// cart.items.append("Armut") ❌ HATA
items sadece ShoppingCart içinde değiştirilebilir, dışarıya immutable bir koleksiyon gibi görünür.
6. private(set) ile Diğer Erişim Seviyeleri
private(set) tek başına kullanılmaz; erişim seviyeleri ile kombine edilebilir:
| Tanım | Anlamı |
|---|---|
private(set) | Setter sadece aynı dosya/extension içinde kullanılabilir |
fileprivate(set) | Setter sadece aynı dosya içinde kullanılabilir |
internal private(set) | Getter her yerden okunur (internal), setter sadece aynı dosya/extension içinde |
public private(set) | Getter public, setter private |
open private(set) | Getter open, setter private |
Örnek:
public private(set) var status: String = "Idle"
Bu sayede framework kullanıcısı status’u okuyabilir ama değiştiremez.
7. Alternatif Yöntemler
- Tamamen private property + public getter
class Example {
private var _value: Int = 0
var value: Int { _value }
}
private(set) bunu daha kısa yapmanın bir yoludur.
- Immutable struct + yeni instance yaratma
struct ImmutableCounter {
let count: Int
func increment() -> ImmutableCounter {
ImmutableCounter(count: count + 1)
}
}
Bu tamamen farklı bir yaklaşım ama mantık aynı: dışarıdan değiştirme engellenir.
8. Sonuç
private(set) Swift’te hem temiz kod hem de güvenli state yönetimi için kritik bir araçtır.
- Encapsulation sağlar
- Dışarıya immutable bir API verir
- Kodun yanlış kullanılmasını önler
Özellikle MVVM, VIPER gibi mimarilerde ViewModel → View veri akışında çokça kullanılır.