some View, SwiftUI’nin çalışması için gerekli olan temel bir Swift sözdizimsel yapısıdır. Apple Swift Book, 2024’e göre, some View, derleme zamanında sıkı tür kontrolünü korurken belirli dönüş türünü gizleyen opak bir türdür (opaque type). Bu yapı, View protokolünün uygulama detaylarını açığa çıkarmadan tek bir body imzasına sahip olmasını sağlar.
Önemli Noktalar
some View, Swift 5.1’de tanıtılan bir opak tür sözdizimidir. View protokolünün body özelliğinin dönüş türü olarak kullanılır. some View gösterimi şu anlama gelir: “fonksiyon veya özellik, View protokolüne uyan somut bir tür döndürür, ancak çağıran kod bunun hangisi olduğunu bilmez ve bilmemelidir”.
Opak tür kavramı, genel programlamanın (generics) ters yüzüdür. Generics, çağıran kodun türü belirlemesine izin verirken, opak tür uygulamanın türü belirlemesine ve bunu çağırandan gizlemesine olanak tanır. Bu, geliştiriciye sözleşmeyi değiştirmeden iç uygulamayı değiştirme özgürlüğü verir.
Swift Evolution SE-0244’e göre, opak türler SwiftUI’yi ve bu yapı olmadan dönüş türü olarak kullanılamayan ilişkili türlere (PAT) sahip protokol desenini desteklemek için eklenmiştir.
Some View olmadan, body imzası imkansız olurdu: View protokolünün, View’e uyan ilişkili bir Body türü vardır. Eğer body basitçe View’i (bir protokol olarak) döndürseydi, Swift dönüş konumunda Self gereksinimleri olan protokollerle çalışamazdı. Some View, somut ancak gizli bir tür sağlayarak bu sorunu çözer.
Opak tür, derleyici için somut, geliştirici için soyut davranan özel bir tür türüdür. Derleyici some View gördüğünde, uygulamayı analiz eder ve tam dönüş türünü belirler. Bu tür sabitlenir ve dinamik dağıtım olmadan kod üretimi için kullanılır.
struct SimpleView: View {
var body: some View {
Text("Merhaba")
}
}
// Compiler sees: body -> Text, not some View
Çalışma prensibi: Swift derleyicisi, uygulamadan somut türü çıkarır. Yukarıdaki örnekte, body yalnızca Text içerir, bu nedenle derleyici, imza some View olarak yazılmış olsa bile body’nin tam olarak Text döndürdüğünü bilir. Bu, sanal yöntem tablosu olmadan doğrudan çağrı ve satiriçi (inlining) olasılığı olmak üzere iki optimizasyon sağlar.
Body’nin uygulaması değişirse (örneğin, Text yerine Text ve Button’dan oluşan bir VStack döndürülürse), derleyici somut türü yeniden tanımlar. Ancak çağıran kod (SwiftUI) için imza aynı kalır — some View. Bu, generics’in ters yüzüdür: çağıran kod, uygulama değişikliklerine bağlı değildir.
Opak türlerin temel kurallarından biri: some View döndüren bir fonksiyon veya özellik her zaman aynı somut türü döndürmelidir. Bir if dalında Text, diğerinde Image döndüremezsiniz. Bu sınırlama derleyici tarafından kontrol edilir ve çağıran kod için bir garanti görevi görür.
struct BadView: View {
var flag: Bool
var body: some View {
if flag {
Text("Doğru") // Hata: Text vs VStack
} else {
VStack {
Text("Yanlış")
Image(systemName: "xmark")
}
}
}
}
Bu sorunu çözmek için, farklı dalları ConditionalContent koşullu kapsayıcısına saran @ViewBuilder kullanılır. Body üzerindeki @ViewBuilder ek açıklaması SwiftUI’de standart bir uygulamadır, ancak body yalnızca tek bir ifade içeriyorsa örtük olabilir.
AnyView, View’in somut uygulamasını silen bir türdür (type erasure). Herhangi bir View’i tek bir sarmalayıcıya sararak farklı türlerdeki View’lerin aynı kapsayıcıda depolanmasına olanak tanır. Some View’in aksine, AnyView çalışma zamanında çalışır ve sarma ve açma için ek yük getirir.
| Kriter | some View | AnyView |
|---|---|---|
| Çözülme zamanı | derleme | çalışma |
| Performans | doğrudan çağrı, ek yük yok | existential container’a sarma |
| Tür esnekliği | tek somut tür | herhangi bir View türü |
| Dinamik değişim | desteklenmez | çalışma zamanında desteklenir |
| Kullanım önceliği | mümkün olduğunda her zaman | yalnızca some View imkansız olduğunda |
| PAT protokol desteği | evet | evet |
AnyView ne zaman kullanılır: yalnızca çalışma zamanında dinamik tür değişimi gerektiği için some View’in mümkün olmadığı durumlarda. Örneğin, bir sözlükten View döndürürken veya somut türün her seviyede değişmesi gereken özyinelemeli bir yapıda. AnyView en aza indirilmelidir, çünkü her sarma SwiftUI optimizasyonlarını devre dışı bırakır.
Yaygın yanılgı: AnyView, body’deki farklı türler sorununu çözmez — bunu @ViewBuilder çözer. AnyView türü siler ancak derleyicinin tek bir tür çıkarmasına yardımcı olmaz. Koşullu mantık için @ViewBuilder ve yalnızca dinamik dağıtım için AnyView kullanın.
@ViewBuilder, özellikle some View ile çalışmak için tasarlanmış bir result builder’dır. Tek bir dönüş türünü korurken body’de koşullu mantık (if/else, switch) ve birden çok ifade kullanılmasına olanak tanır. ViewBuilder, birden çok ifadeyi otomatik olarak TupleView’a ve koşullu dalları ConditionalContent’a sarar.
struct ProfileView: View {
let user: User?
@ViewBuilder
var body: some View {
if let user {
UserCard(user: user)
Text("Çevrimiçi")
.font(.caption)
} else {
ProgressView("Loading...")
}
}
}
Nasıl çalışır: @ViewBuilder kod bloğunu analiz eder ve uygun buildBlock, buildOptional veya buildEither çağrısını oluşturur. Koşullu mantık için ConditionalContent oluşturulur — dalların içindeki somut türlerini gizleyen ancak derleyici için kendisi tek bir tür olan ortak bir tür. Bu, farklı somut türler sorununu çözer.
@ViewBuilder olmadan, birden çok ifade veya koşullu mantık içeren bir body özelliği derleme hatasına neden olur. Bu nedenle SwiftUI, body’ye @ViewBuilder’ı örtük olarak uygular ve özel özellikler ve fonksiyonlar için açıkça eklenmesi gerekir.
@ViewBuilder iç içe kullanılabilir: bir ViewBuilder başka bir ViewBuilder’ın içinde. Bu, farklı seviyelerde koşullarla karmaşık hiyerarşiler oluşturmayı sağlar. Ancak, derin iç içe kullanım okunabilirliği zorlaştırır, bu nedenle iç içe koşulları ayrı View bileşenlerine çıkarmak önerilir.
Örnek 1: hesaplanan bir özellikten özel bir View döndürme. Bir özellik, iç bileşimi gizleyerek some View döndürebilir. Bu, genel arayüzü değiştirmeden kodun yeniden düzenlenmesine olanak tanır.
struct ArticleView: View {
var body: some View {
CardView {
HeaderView()
ContentView()
FooterView()
}
}
}
struct CardView<Content: View>: View {
let content: Content
var body: some View {
content
.padding(16)
.background(.white)
.cornerRadius(12)
.shadow(radius: 4)
}
}
Örnek 2: @ViewBuilder aracılığıyla bir View’i closure olarak geçirme. Bu desen, standart SwiftUI kapsayıcılarında (VStack, HStack, List) kullanılır ve özel bileşenlerde uygulanabilir.
struct CustomContainer<Content: View>: View {
@ViewBuilder let content: () -> Content
var body: some View {
VStack(alignment: .leading) {
content()
}
.padding(20)
}
}
Örnek 3: some View döndüren bir fabrika fonksiyonu. Uygulamayı açığa çıkarmadan parametrelere göre View oluşturmayı sağlar. Bu, özellikle kütüphaneler ve yeniden kullanılabilir bileşenler için kullanışlıdır.
func makeIcon(for status: Status) -> some View {
switch status {
case .success:
Image(systemName: "checkmark.circle.fill")
.foregroundColor(.green)
case .error:
Image(systemName: "xmark.circle.fill")
.foregroundColor(.red)
case .pending:
ProgressView()
}
}
Sıkça Sorulan Sorular
some View opak bir türdür, yani View protokolüne uyan somut bir tür döndürülür. Somut tür derleyici tarafından belirlenir ancak çağıran koddan gizlenir. Bu, uygulama detaylarını açığa çıkarmadan sıkı tür kontrolü sağlar.
some View sıfır ek yükle derleme zamanında çözülür. AnyView, existential container’a sarma ek maliyetiyle çalışma zamanında type erasure kullanır. Mümkün olduğunda her zaman some View kullanın, AnyView’i yalnızca dinamik tür değişimi için kullanın.
Opak tür, tüm dönüş yolları için tek bir somut tür gerektirir. Farklı türlerle if/else bu gereksinimi ihlal eder. @ViewBuilder, dalları ConditionalContent — somut uygulamaların farklılıklarını gizleyen tek bir tür — içine sararak sorunu çözer.
some View performansı düşürmez — derleyici tam türü bilir ve doğrudan kod üretir. Tersine, any View (bir protokol olarak) dinamik dağıtım gerektirir. some View, SwiftUI’nin tasarımına yerleşik bir optimizasyon mekanizmasıdır.
Evet, some SwiftUI’ye bağlı olmayan genel bir Swift 5.1 yapısıdır. Herhangi bir protokolle kullanılabilir: some Equatable, some Codable, some Collection. Bu, [String: [Int]] gibi karmaşık iç içe türleri gizlemek için kullanışlıdır.
Özet
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.
Ayrıca okuyun