返回顶部
s

swiftdata-patternsSwiftData模式

SwiftData best practices, batch queries, N+1 avoidance, and model relationships for macOS/iOS apps

作者: admin | 来源: ClawHub
源自
ClawHub
版本
V 1.0.0
安全检测
已通过
116
下载量
免费
免费
0
收藏
概述
安装方式
版本历史

swiftdata-patterns

SwiftData 模式

适用于 macOS/iOS 应用程序的专家级 SwiftData 模式。针对性能、关系和生产就绪性进行了优化。

使用时机

在以下情况下使用此技能:

  • - 设计 SwiftData 模型时
  • 编写 SwiftData 查询时
  • 优化批量操作时
  • 设置模型关系时
  • 处理持久化层架构时
  • 避免 N+1 查询问题时



核心原则

1. 模型设计

swift
@Model
final class YourModel {
@Attribute(.unique) var id: UUID

// 对大数据使用外部存储
@Attribute(.externalStorage) var largeData: Data?

// 带级联删除的关系
@Relationship(deleteRule: .cascade)
var children: [ChildModel]?

init(id: UUID = UUID()) {
self.id = id
}
}

2. FetchDescriptor 最佳实践

swift
// 使用谓词进行过滤
let descriptor = FetchDescriptor(
predicate: #Predicate { $0.isActive && $0.createdAt >= startDate },
sortBy: [SortDescriptor(\.createdAt, order: .reverse)]
)

// 按 ID 批量获取(避免 N+1)
func fetchModels(by ids: [UUID]) -> [YourModel] {
guard !ids.isEmpty else { return [] }

let descriptor = FetchDescriptor(
predicate: #Predicate { ids.contains($0.id) }
)
return (try? context.fetch(descriptor)) ?? []
}

3. 内存测试模式

swift
@MainActor
final class ModelTests: XCTestCase {
var container: ModelContainer!
var context: ModelContext!

override func setUp() async throws {
try await super.setUp()
let config = ModelConfiguration(isStoredInMemoryOnly: true)
container = try ModelContainer(for: YourModel.self, configurations: config)
context = container.mainContext
}

override func tearDown() async throws {
try await super.tearDown()
container = nil
context = nil
}
}

4. 服务层模式

swift
@MainActor
final class DataService {
nonisolated let container: ModelContainer
let context: ModelContext

init(inMemory: Bool = false) throws {
let configuration = ModelConfiguration(isStoredInMemoryOnly: inMemory)
container = try ModelContainer(for: YourModel.self, configurations: configuration)
context = ModelContext(container)
context.autosaveEnabled = false // 手动保存控制
}

func save() throws {
try context.save()
}
}



性能模式

分块批量插入

swift
extension ModelContext {
func safeBatchInsert(
_ objects: [T],
batchSize: Int = 100
) throws {
for (index, object) in objects.enumerated() {
insert(object)
if index % batchSize == 0 {
try save()
}
}
try save()
}
}

避免 N+1 查询

错误 - N+1 问题:
swift
for reminder in reminders {
let task = service.findIdentityMap(by: reminder.id) // N 次查询!
process(task)
}

正确 - 批量获取:
swift
let ids = reminders.map { $0.id }
let tasks = service.fetchIdentityMaps(by: ids) // 1 次查询!

for (index, reminder) in reminders.enumerated() {
let task = tasks.first { $0.ekIdentifier == reminder.id }
process(task)
}

共享 Fetch Descriptor

swift
@MainActor
final class DataService {
// 非隔离以实现线程安全的 descriptor 访问
nonisolated func descriptorForActiveItems() -> FetchDescriptor {
FetchDescriptor(
predicate: #Predicate { $0.isActive },
sortBy: [SortDescriptor(\.createdAt, order: .reverse)]
)
}

// 在 @Observable ViewModels 中使用
func fetchActiveItems() -> [YourModel] {
try? context.fetch(descriptorForActiveItems()) ?? []
}
}



模型关系

双向链接

swift
@Model
final class Note {
@Attribute(.unique) var id: UUID

// 正向链接
@Relationship(inverse: \Note.backlinks)
var forwardLinks: [Note]?

// 反向链接(自动维护)
var backlinks: [Note]?

init(id: UUID = UUID()) {
self.id = id
}
}

级联删除

swift
@Model
final class Parent {
@Attribute(.unique) var id: UUID

@Relationship(deleteRule: .cascade) // 自动删除子项
var children: [Child]?
}

@Model
final class Child {
@Attribute(.unique) var id: UUID
var parent: Parent?
}



配置最佳实践

App Group 支持

swift
private static func createConfiguration(inMemory: Bool) throws -> ModelConfiguration {
if inMemory {
return ModelConfiguration(isStoredInMemoryOnly: true)
}

let appGroupID = group.your.app.id
guard let containerURL = FileManager.default.containerURL(
forSecurityApplicationGroupIdentifier: appGroupID
) else {
// 回退到沙盒
return createSandboxConfiguration()
}

let dataURL = containerURL.appendingPathComponent(App_Data)
try? FileManager.default.createDirectory(at: dataURL, withIntermediateDirectories: true)
let storeURL = dataURL.appendingPathComponent(App.sqlite)

return ModelConfiguration(url: storeURL, cloudKitDatabase: .automatic)
}



测试指南

Given-When-Then 模式

swift
func testBatchFetchPerformance() async throws {
// Given: 创建测试数据
let ids = (0..<100).map { _ in
let model = service.createModel()
try? context.save()
return model.id
}

// When: 批量获取
let start = Date()
let results = service.fetchModels(by: ids)
let duration = Date().timeIntervalSince(start)

// Then: 验证
XCTAssertEqual(results.count, 100)
XCTAssertLessThan(duration, 0.5, 批量获取应该很快)
}

谓词测试

swift
func testPredicateFiltering() async throws {
// Given
let activeModel = service.createModel(isActive: true)
let inactiveModel = service.createModel(isActive: false)
try? context.save()

// When
let descriptor = FetchDescriptor(
predicate: #Predicate { $0.isActive }
)
let results = try context.fetch(descriptor)

// Then
XCTAssertEqual(results.count, 1)
XCTAssertEqual(results.first?.id, activeModel.id)
}



最佳实践


实践原因
在服务上使用 @MainActorSwiftData 上下文绑定主线程
大数据使用外部存储
防止数据库膨胀 |
| 关系使用批量获取 | 避免 N+1 查询 |
| 手动控制自动保存 | 防止意外中间保存 |
| 测试使用内存配置 | 隔离测试状态 |
| 非隔离的 fetch descriptor | 线程安全的 descriptor 访问 |


常见陷阱


陷阱后果预防措施
N+1 查询同步性能慢使用批量 fetch(by: [ID])
忘记 @MainActor
运行时崩溃 | 所有 SwiftData 服务必须隔离 |
| 大数据内联存储 | 数据库膨胀 | 使用 @Attribute(.externalStorage) |
| 自动保存冲突 | 意外状态变化 | 设置 autosaveEnabled = false |
| 缺少级联删除 | 孤立记录 | 使用 deleteRule: .cascade |


在测试中运行 SwiftData

bash

使用 SwiftData 测试


xcodebuild test -scheme YourApp \
-destination platform=macOS \
-only-testing:YourAppTests/ModelTests/testBatchFetch

标签

skill ai

通过对话安装

该技能支持在以下平台通过对话安装:

OpenClaw WorkBuddy QClaw Kimi Claude

方式一:安装 SkillHub 和技能

帮我安装 SkillHub 和 swiftdata-patterns-1776021855 技能

方式二:设置 SkillHub 为优先技能安装源

设置 SkillHub 为我的优先技能安装源,然后帮我安装 swiftdata-patterns-1776021855 技能

通过命令行安装

skillhub install swiftdata-patterns-1776021855

下载

⬇ 下载 swiftdata-patterns v1.0.0(免费)

文件大小: 3.35 KB | 发布时间: 2026-4-13 12:14

v1.0.0 最新 2026-4-13 12:14
Initial release of swiftdata-patterns with best practices and advanced patterns for SwiftData on macOS/iOS:

- Covers model design, query optimization, and relationship handling.
- Provides batch fetching and N+1 query avoidance techniques.
- Includes service layer and in-memory test patterns.
- Lists configuration practices for app group and test environments.
- Documents common pitfalls, solutions, and performance patterns.
- Offers code examples for testing and practical usage scenarios.

Archiver·手机版·闲社网·闲社论坛·智能体自动化市场· 多链控股集团有限公司 · 苏ICP备2025199260号-1

Powered by Discuz! X5.0   © 2024-2026 闲社网·AI智能体论坛·AI自动化解决方案·http://xianshe.com

p2p_official_large
返回顶部