edit | blame | history | raw

核心架构与业务逻辑

  • 整理日期:2026-06-11
  • 复核日期:2026-06-15
  • 依据产品版本:TagLauncher 7.9.1,Build 20260614.1454
  • 版本依据:src/Apptag/Info.plistsrc/CHANGELOG.mdsrc/Release/AppStore-7.9.1-20260614.1454/QA_RELEASE_EVIDENCE.md
  • 配套图示:01-核心架构与业务逻辑.drawio

一句话定位

TagLauncher 是一个 macOS 菜单栏/桌面工具。它扫描本机标准 App 目录,生成带标签、备注和使用行为的本地应用库;用户通过全屏 overlay 的 App Grid 或 Quick Search 打开应用,并可维护标签体系、备注、显示偏好和本地数据备份。

技术栈与部署形态

运行时代码是单体 macOS App,不使用 Xcode 工程文件构建,而由 src/build.sh 直接调用 swiftc 编译 src/Apptag/**/*.swift。主要框架包括:

  • SwiftUI:App 入口、主界面组合、设置页、部分弹窗和编辑态 UI。
  • AppKitNSPanelNSWindow、菜单栏、全局/局部事件、NSCollectionView、自绘 App Grid、文件面板。
  • Carbon:固定全局快捷键注册,主快捷键为 ⌥⇧Space,Quick Search 快捷键为 Fn+Space
  • CoreServices:Spotlight metadata 读取,用于应用显示名和系统应用名称候选。
  • Compression:运行时加载 deflate 压缩后的 Smart Start 与 Apple 默认应用多语言资源。

App 是 LSUIElement=true 的菜单栏工具,同时支持按用户设置显示 Dock 图标。当前 bundle id 是 com.taglauncher.app

顶层模块职责

模块 主要文件 职责
App 生命周期与窗口编排 ApptagApp.swiftOverlayWindowController.swiftProcessSingleton.swift 单实例、菜单栏、快捷键、Dock/activation policy、overlay/window 层级、Quick Search 事件、Settings 附着关系
主业务 UI ContentView.swift App Grid、Quick Search 状态、编辑模式、Smart Start 提示、备注气泡、刷新与 snapshot 应用
App Grid 与拖拽 AppGridCollectionView.swiftAppDragCoordinator.swiftTagNavigationView.swift AppKit-backed 网格布局、标签导航、长按拖拽、drop target、容器内排序、使用技巧悬浮条、hover、滚动期间状态抑制
数据与索引 DataLayer.swiftAppLibraryController.swift App 扫描、名称抽取、TagDatabase 本地存储、标签 CRUD、应用库 snapshot
Quick Search QuickSearch.swift 搜索文档生成、搜索打分、行为 boost、独立面板、键盘焦点和结果列表
Smart Start SmartStartService.swiftSmartCategorizationDraft.swiftSmartCategory.swift 首次/手动智能分类、catalog 匹配、默认备注、备份、恢复
Apple 默认应用 AppleDefaultAppCatalog.swiftResearch/AppleDefaultApps Apple 系统应用分类、熟悉/不常用判定、多语言显示名和默认备注
本地化与设置 L10n.swiftPreferencesView.swiftAppDefaults.swift 29 语言、设置页、启动登录、导入导出、系统方案应用
构建与 QA build.shmake_dmg.shScripts/*.sh 编译、资源压缩复制、签名、DMG、窗口/资源/搜索专项 QA

启动链路

TagLauncherApp@main 入口,初始化时调用 TagLauncherProcessSingleton.acquireOrHandOffAndExit()。如果已有实例持有锁,新实例会通过 DistributedNotificationCenter--show-overlay 意图移交给旧实例,然后退出,避免多个 Dock 图标或多个菜单栏实例。

主实例启动后,AppDelegate.applicationDidFinishLaunching 做以下初始化:

  1. 注册默认设置:AppDefaults.register()
  2. 加载语言:L10n.setup()
  3. 迁移默认分组名到语言无关 key:migrateDefaultGroupName()
  4. 初始化本地标签库:TagDatabase.seedDefaultTags()
  5. 同步 Dock/菜单栏 chrome:syncChromeSettings(force: true)
  6. 注册两个固定热键:registerConfiguredHotkeys()
  7. 安装窗口、编辑态、Quick Search、语言、外部激活等通知监听。
  8. 设置 LaunchAgent 登录启动。
  9. 后台预热 App 索引:warmAppIndexInBackground()
  10. 启动后对默认备注执行当前语言重本地化:relocalizeDefaultAppNotesForCurrentLanguageAsync()

核心业务闭环

TagLauncher 的核心闭环是“扫描应用 -> 合并本地数据 -> 生成 snapshot -> 展示/搜索 -> 用户修改 -> 刷新 snapshot”。

  1. AppIndexer.scan 扫描标准 App 路径,抽取 bundle id、文件名、Finder/Spotlight 名称、InfoPlist 多语言名、Apple catalog 名称和图标。
  2. TagEditor.reconcileScannedAppsTagDatabase.Store 合并,处理新增/删除 App、Apple 默认备注、不熟悉系统应用标记。
  3. SmartStartService.runIfNeeded 在 catalog 版本落后或首次运行时生成或应用智能分类。
  4. AppLibraryController.makeSnapshot 产出 AppLibrarySnapshot,同时包含:
  • apps:已标注标签、备注、不常用状态的 App 列表。
  • quickSearchDocuments:Quick Search 搜索文档。
  • tagColors:标签颜色。
  • tagOrder:标签展示顺序。
  • containerAppOrder:稳定容器 ID 到 App path 顺序的映射。
  1. ContentView.applyAppLibrarySnapshot 把 snapshot 写入 UI 状态,重建 App Grid 分组,并刷新 Quick Search 结果。
  2. 用户通过标签编辑、拖拽、备注编辑、导入、系统方案应用等操作写入 TagDatabase
  3. 写入后通过 refreshApps.tagLauncherDataDidChange 触发新一轮 snapshot。

本地数据边界

运行时用户数据不写入仓库,默认写入:

  • ~/Library/Application Support/TagLauncher/tags.json
  • ~/Library/Application Support/TagLauncher/SmartStartBackups/
  • ~/Library/Application Support/TagLauncher/CategorySchemeBackups/
  • ~/Library/Application Support/TagLauncher/TagLauncher-diagnostics.log,仅在 diagnosticLoggingEnabled 开启时写入

TagDatabase.Store 是核心本地数据模型,包含标签定义、App 到标签的映射、标签顺序、容器内 App 顺序、不常用标记、打开次数、备注、备注来源 metadata、Smart Start 状态、分类方案状态。

关键设计判断

  1. 单 snapshot 管线:App Grid 和 Quick Search 共享 AppLibrarySnapshot,减少“网格看得到但搜索搜不到”的分叉风险。
  2. AppKit 接管高风险 UI:窗口、Quick Search 面板、App Grid、标签导航、结果列表都大量使用 AppKit,规避 SwiftUI 在全屏、Split View、滚动和焦点上的不稳定。
  3. 默认数据与用户数据分离:Smart Start 默认备注、Apple 默认备注、用户手动备注通过 AppNoteOrigin 区分,避免切语言或刷新时覆盖用户编辑。
  4. 系统应用单独 catalog:Apple 默认应用从 Smart Start 大 catalog 中拆出,保证系统 App 的名称、分类和默认备注质量独立受控。
  5. 容器排序使用稳定 ID:7.9.x 起 App Grid 容器内排序写入 containerAppOrder,按 uncategorizedappleBuiltIntag:<name>system:<id> 保存,避免语言切换导致顺序丢失。
  6. 窗口策略优先真实 macOS 行为:overlay 在全屏/Split View 下会避免 Space 切换,Quick Search 和 Settings 均与 overlay 建立明确层级关系。

高维护风险区

  • ApptagApp.swift 同时承担生命周期、菜单、快捷键、Dock policy、窗口路由和 Quick Search 状态协调,改动需结合 window_logic_qa.sh 做回归。
  • ContentView.swift 聚合主业务 UI 和状态机,刷新、Quick Search、Smart Start、拖拽、备注弹窗相互影响,改动需确认 modal/backdrop 抑制是否仍正确。
  • DataLayer.swift 是扫描、名称、存储、标签 CRUD 和容器排序归一化的交汇点,名称解析、helper 过滤或 containerAppOrder 一旦改动需同步跑 Quick Search 名称 QA 和排序数据 QA。
  • SmartStartService.swiftAppleDefaultAppCatalog.swift 有默认备注来源保护逻辑,改动需跑 SmartStart、Apple resource 和 note policy QA。

新同事接手建议

先从 AppLibraryController.refresh 跟到 ContentView.refreshApps,再从 AppDelegate.showQuickSearchFromGlobalHotkey 跟到 QuickSearchEngine.search。这两条线分别对应产品最核心的 App Grid 和 Quick Search。理解这两条线后,再看窗口层级、拖拽和 Smart Start,成本最低。