Section 7/181 menit
7. Relasi Antar Model
7. Relasi Antar Model
SwiftData mendukung relasi one-to-one, one-to-many, dan many-to-many dengan @Relationship.
One-to-Many
swift
@Model
final class Author {
var name: String
var biography: String
// One Author → many Books
@Relationship(deleteRule: .cascade, inverse: \Book.author)
var books: [Book] = []
init(name: String, biography: String = "") {
self.name = name
self.biography = biography
}
}
@Model
final class Book {
var title: String
var publishedYear: Int
// Many Books → one Author (optional karena buku bisa orphan)
var author: Author?
init(title: String, publishedYear: Int) {
self.title = title
self.publishedYear = publishedYear
}
}
Delete Rules
| Delete Rule | Perilaku |
|---|---|
.nullify (default) |
Set relasi ke nil saat parent dihapus |
.cascade |
Hapus semua child saat parent dihapus |
.deny |
Tolak penghapusan parent jika masih punya child |
.noAction |
Tidak ada aksi — developer bertanggung jawab |
Many-to-Many
swift
@Model
final class Book {
var title: String
@Relationship(inverse: \Tag.books)
var tags: [Tag] = []
init(title: String) {
self.title = title
}
}
@Model
final class Tag {
var name: String
var color: String
@Relationship(inverse: \Book.tags)
var books: [Book] = []
init(name: String, color: String = "blue") {
self.name = name
self.color = color
}
}
// Penggunaan
let book = Book(title: "Clean Code")
let tag = Tag(name: "Programming")
context.insert(book)
context.insert(tag)
book.tags.append(tag) // otomatis update tag.books juga
try context.save()
Relasi Nested dan Lazy Loading
SwiftData menggunakan lazy loading untuk relasi — data relasi hanya diambil dari disk saat property diakses pertama kali. Ini efisien untuk graph model yang besar.
swift
@Model
final class Department {
var name: String
@Relationship(deleteRule: .cascade, inverse: \Employee.department)
var employees: [Employee] = [] // tidak di-load sampai diakses
var headCount: Int { employees.count } // akses ini trigger lazy load
init(name: String) { self.name = name }
}