SwiftData 学习笔记:relationship

前言

在前几篇文章中,我们介绍了 SwiftData 的简单使用和增删改查操作,以及数据的排序过滤和 Container、context 的概念介绍。

本篇文章主要来讲解一下 SwiftData 中的 relationship。

自动推断

SwiftData 的 relationship 是可以通过你定义的模型结构体自动推断出来的。也可以通过 @Relationship 宏来显式声明。

一般来说,只有当你不想使用默认配置的时候,才需要显式声明。通常情况下,你是用不到 @Relationship 的。

比如下面的这个例子:

swift 复制代码
@Model
class School {
    var name: String
    var students: [Student]

    init(name: String, students: [Student]) {
        self.name = name
        self.students = students
    }
}

@Model
class Student {
    var name: String
    var school: School

    init(name: String, school: School) {
        self.name = name
        self.school = school
    }
}

我们定义了一个 School 和一个 Student的类,并且,在 Student 中使用了 School 声明属性;在 School 中使用 Student 声明一个数组。从上述代码中,SwiftData 可以推断出:

  • 每个学校可以有很多学生
  • 每个学生只属于一所学校

但是,这两者并不是耦合在一起的,它们是分开的。如果我们创建了一个学生并设置了它的 school属性,SwiftData 不理解如何将该学生添加到该学校的 students 数组中,它不会自动推断出这种关系是双向的。

如果,我们将 Student 改成下面的代码:

swift 复制代码
@Model
class Student {
    var name: String
    var school: School?

    init(name: String, school: School?) {
        self.name = name
        self.school = school
    }
}

唯一的变化是我们将 school 声明为了可选类型,这意味着它的值可能为空。做出这一改动是基于安全的考虑:

  • 如果学生和学校之间存在关系,那么设置学生的 school 属性应该将其添加到学校的学生列表中或将其从学校的学生列表中删除
  • 同样,从学校的学生列表中添加或者删除学生,也应该同步修改学生的 school 属性
  • 那么,如果你将一名学生从一所学校中删除,而不将其添加到另一所学校,会发生什么情况呢?

当我们将 school 属性声明为非可选值的时候,即意味着上述情况是不可能发生的,学生必须归属于一所学校。如果学生的 school 属性没有被赋值,SwiftData 会触发 crash,因为我们将其置于无效状态。

另一方面,一旦我们将 school 属性设置为可选属性,这个危险就消失了:从 students 数组中删除一个学生只会将他们的 school 属性设置为 nil ,所以就没有了崩溃风险。

这里的规则很简单:如果可以安全地推断关系,SwiftData 就会去自动推断。

显式声明

很多时候,这还不够,我们可以在两个模型之一上使用 @Relationship宏创建显式关系,它显式地说明连接。例如,我们可以改变Student类,让它的school属性看起来像这样:

java 复制代码
@Relationship(inverse: \School.students) var school: School

这可以是可选的,也可以是非可选的------这里没有安全限制,因为你已经准确地告诉 SwiftData 你想要什么。

或者,我们可以更改 School 类,使其学生属性如下所示:

java 复制代码
@Relationship(inverse: \Student.school) var students: [Student]
相关推荐
恋猫de小郭16 小时前
Flutter Widget Preview 功能已合并到 master,提前在体验毛坯的预览支持
android·flutter·ios
点金石游戏出海21 小时前
每周资讯 | Krafton斥资750亿日元收购日本动画公司ADK;《崩坏:星穹铁道》新版本首日登顶iOS畅销榜
游戏·ios·业界资讯·apple·崩坏星穹铁道
旷世奇才李先生1 天前
Swift 安装使用教程
开发语言·ios·swift
90后的晨仔1 天前
Xcode16报错: SDK does not contain 'libarclite' at the path '/Applicati
ios
finger244801 天前
谈一谈iOS线程管理
ios·objective-c
Digitally1 天前
如何将大型视频文件从 iPhone 传输到 PC
ios·iphone
梅名智1 天前
IOS 蓝牙连接
macos·ios·cocoa
美狐美颜sdk1 天前
跨平台直播美颜SDK集成实录:Android/iOS如何适配贴纸功能
android·人工智能·ios·架构·音视频·美颜sdk·第三方美颜sdk
恋猫de小郭2 天前
Meta 宣布加入 Kotlin 基金会,将为 Kotlin 和 Android 生态提供全新支持
android·开发语言·ios·kotlin
泓博2 天前
Objective-c把字符解析成字典
开发语言·ios·objective-c