Sonodex 开发企划,技术架构与实现规范 (v1.0)
1. 项目概述
Sonodex 是一款专为音乐制作人设计的本地 MIDI 与音频采样管理系统。其核心任务是高效索引、检索并管理分布在本地磁盘上的数十万计媒体素材,提供秒级的搜索响应,并确保数据状态与物理文件的高度一致性。
1.1 核心原则
- 稳定性优先: 拒绝隐式缓存,所有数据变更必须透明且可追溯。
- 性能导向: 针对 100,000+ 记录优化,确保 UI 线程永不阻塞。
- 数据主权: 采用开放格式的 SQL 数据库,不依赖黑盒框架。
2. 技术栈选型 (Tech Stack)
| 维度 | 技术选型 | 说明 |
|---|---|---|
| 开发平台 | macOS 14.0+ | 针对 Apple Silicon 与原生系统特性优化。 |
| 编程语言 | Swift 5.9+ | 利用强类型、值类型语义与并发模型(Concurrency)。 |
| UI 框架 | SwiftUI | 声明式 UI,处理状态驱动的复杂视图。 |
| 持久化层 | GRDB.swift (SQLite) | 放弃 SwiftData,选择类型安全的原生 SQL 包装器。 |
| 并发处理 | Swift Concurrency | 使用 async/await 处理文件 IO 与重型检索。 |
3. 系统架构设计
系统采用 层级解耦架构,确保数据库持久层与 UI 表现层之间有明确的边界,彻底消除“幽灵缓存”。
3.1 实体模型 (Entity Model)
弃用 Class 引用语义,全案使用 Value-based Struct。
struct SonodexEntry: Codable, FetchableRecord, MutablePersistableRecord {
var id: Int64?
var fileName: String // 文件名(索引核心)
var relativePath: String // 相对路径/绝对路径
var duration: Double // 音频长度
var fileType: String // wav, mid, aif 等
var tags: String? // 预留标签字段
var bookmarkData: Data? // macOS 权限持久化(重要)
}
4. 持久化层实现路径 (The SQL Path)
4.1 数据库初始化与迁移
使用 DatabasePool 以支持多线程并发读取,通过 DatabaseMigrator 管理 Schema 版本。
class DatabaseManager {
static let shared = DatabaseManager()
let dbPool: DatabasePool
private init() {
// 配置数据库存放于 Application Support
let path = try! FileManager.default
.url(for: .applicationSupportDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
.appendingPathComponent("sonodex.sqlite").path
dbPool = try! DatabasePool(path: path)
try! setupMigrations()
}
private func setupMigrations() throws {
var migrator = DatabaseMigrator()
migrator.registerMigration("v1_create_entries") { db in
try db.create(table: "sonodex_entries") { t in
t.autoIncrementedPrimaryKey("id")
t.column("fileName", .text).notNull().indexed()
t.column("relativePath", .text).notNull().unique()
t.column("duration", .double)
t.column("fileType", .text)
}
}
try migrator.migrate(dbPool)
}
}
4.2 高性能检索策略 (FTS5)
针对数十万条记录,传统的 LIKE 查询在大规模文本下表现不佳。Sonodex 必须启用 SQLite 的 FTS5 (Full-Text Search) 扩展模块。
- 实现方式: 建立虚拟表(Virtual Table),将文件名映射至全文搜索索引。
- 预期性能: 50 万条记录下,关键词检索耗时控制在 10ms 以内。
5. 关键技术方案
5.1 权限与路径一致性
macOS 的沙盒机制可能导致路径失效。
- 解决方案: 存储
Security-Scoped Bookmarks。即使外部文件夹重命名,只要文件 UUID 未变,Sonodex 依然能通过 Data 重新解析出正确的 URL。
5.2 零缓存 UI 更新
使用 GRDB 的 ValueObservation。
- 机制: 订阅 SQLite 的事务提交通知。当文件扫描器(Scanner)在后台写入新采样时,UI 自动触发重新查询。
- 隔离: 查询结果通过
map转换为视图快照(Snapshot Structs),确保 View 层无法意外修改数据库实体。
6. 开发平台与环境建议
- IDE: Xcode 15.0+。
- 数据库调试工具: 推荐使用 TablePlus。它能直接打开
.sqlite文件,实时监控扫描器写入的数据流。 - 性能监控: 利用 Xcode Instruments 的 Core Data (SQLite) 工具 观察 IO 峰值和查询耗时。
7. 下一步实施方案
- 基础设施搭建: 在 Xcode 引入 GRDB 框架并配置
DatabaseManager单例。 - Schema 迁移: 将原 Python (LMA) 的字段映射至 Swift Struct。
- 扫描引擎开发: 实现基于
FileManager的递归扫描,并使用dbPool.write进行批量异步入库。 - FTS5 集成: 为搜索框添加全文检索能力。