Öncelikle yeni frameworklere geliştirme aşamasında çok olumlu bakan insanlardan birisi değilim. Fakat bu sefer yanıldığımı farkettim. SwiftData bu hali ile bence olmuş.

Geçtiğimiz günlerde freelance bir proje yaparken Coredata'nın bazı özelliklerinin kısıldığını, yapısında bazı değişiklikler yapıldığını farketmiştim. Tabi bu her zaman Apple politikası gereği yeni bir ürün gelirken yapılan bir olay bunu bilmemek hatadır. Apple yeni ürün çıkaracağında bile marketini kapatır. İnsanları yeni ürüne odaklar.

Sonuç olarak Swift Data aslında baya baya arka planda Coredata kullanan ama onun baya baya basitleştirilmiş, otomatize edilmiş bir hali gibi düşünebilirsiniz. İlk testlerimde ve test app modellerinde o acayip core data şemalaları ile falan uğraşmanıza gerek kalmadığını gördüm. Baya güzel flexible olmuş. Tabi SwiftData sadece 17 + üzeri versiyonlara hizmet verdiğinden henüz büyük bir kullanım alanı yok. Profesyonel seviyede işler Coredata mimarisinde devam edecektir. Tabi ekürisi Realm de ayrı bir dünya...

Neyse hemen örnek yapıya geçelim.

Şimdi ilk olarak her zamanki gibi bir modele ihtiyacımız var. Genel olarak aynı ama küçük birşey ekleyeceğiz.


import Foundation
import SwiftData

@Model
final class Person {

var personName: String
var personAge: Int
var personIsHired: Bool
var timeStamp: Date

init(personName: String, personAge: Int, personIsHired: Bool = false, timeStamp: Date) {
self.personName = personName
self.personAge = personAge
self.personIsHired = personIsHired
self.timeStamp = timeStamp
}
}


Farkettiniz import ve @Model

Bunun dışında App'in ana yapısında şöyle bir yapımız olacak.


import SwiftUI
import SwiftData

@main
struct SwiftData_ExampleApp: App {

var body: some Scene {
WindowGroup {
ContentView()
}
.modelContainer(for: Person.self)
}
}


Farkettiniz .model container ekledik ve for Person.self verdik (yani modelimiz üzerinde çalıştırdık bu yapılarda self sağ tarafa geliyor biliyorsunuz, sola değil.)

Content viewimiz ise şu şekilde;


import SwiftUI
import SwiftData

struct ContentView: View {
@Environment(\.modelContext) private var modelContext

@Query private var allPersons: [Person]
@Query(filter: #Predicate { $0.personIsHired == true } ) private var hiredPersons: [Person]
@Query(filter: #Predicate { $0.personIsHired == false } ) private var firedPersons: [Person]



var body: some View {


NavigationView {
List {
Section(header: Text("Hired")) {
ForEach(hiredPersons) { person in

HStack {
Text("Name: \(person.personName)")
Text("Age: \(person.personAge)")

Button {
withAnimation {
person.personIsHired.toggle()

}

} label: {
Image(systemName: person.personIsHired ? "heart.fill" : "heart")
.tint(.red)
}
}
.swipeActions{
Button {
modelContext.delete(person)

} label: {
Image(systemName: "trash")
}

}

}

}

Section(header: Text("Fired")) {
ForEach(firedPersons) { person in

HStack {
Text("Name: \(person.personName)")
Text("Age: \(person.personAge)")

Button {
withAnimation {
person.personIsHired.toggle()

}

} label: {
Image(systemName: person.personIsHired ? "heart.fill" : "heart")
.tint(.gray)
}
}
.swipeActions{
Button {
modelContext.delete(person)
} label: {
Image(systemName: "trash")
}
}
}
}
}

.toolbar {
ToolbarItem {
Button(action: addItem) {
Label("Add Item", systemImage: "plus")
}
}
}
}

}

private func addItem() {
withAnimation {

let newPerson = Person(personName: " \(UUID().uuidString.prefix(10))", personAge: Int.random(in: 18...70), timeStamp: Date())

modelContext.insert(newPerson)

}
}

}


Burada en önemli mevzu üst kısımdaki queryle ve environment yapısı.


@Environment(\.modelContext) private var modelContext

@Query private var allPersons: [Person]
@Query(filter: #Predicate { $0.personIsHired == true } ) private var hiredPersons: [Person]
@Query(filter: #Predicate { $0.personIsHired == false } ) private var firedPersons: [Person]



Swiftdata'nın ilk versiyonlarında predicate sonrası kısmı yoktu. Ama şimdi onu da set etmelisiniz. $0'nin manasını zaten seçili olanı al kısmından hatırlarsınız. Bilmiyorsanız bir zahmet onu bir araştırın. Yapıdaki ikinci Person kafaınızı karıştırabilir ama diğer versiyonlarda syntaxta bir güncelleme yapacaklarını düşünüyorum. Github'da birçok örnek ilk yapıya ait hata verirse böyle düzenlersiniz.


private func addItem() {
withAnimation {

let newPerson = Person(personName: " \(UUID().uuidString.prefix(10))", personAge: Int.random(in: 18...70), timeStamp: Date())

modelContext.insert(newPerson)

}
}


Şu function ile yine coredatadaki gibi insert yapabiliyorsunuz. İnsert için random bir UUID ile username üzerine yine random age değeri artı tarih ile bir dummy data oluşturuyoruz. Aç kapa yaptığınızda verilerin durduğunu göreceksiniz. App'te önce data üretip hired ve fired örneğini göreceksiniz. Tabi biraz süslemişler. Kalpler falan :)

Bence hoş. icloud sync kısımları falan henüz experimental seviyede ama bence hoş. Daha fazla orjinal örnek ile geleceğim.

Buradaki örneğin buggy haline şuradaki github reposundan ulaşabilirsiniz. Ama çalışan halini buradan editlersiniz.

Sevgiler ile Swift ile kalın :) + SwiftUI kıps :)