edit | blame | history | raw

THAW 菜单栏图标隐藏问题专题

更新时间:2026-06-09

这个问题是什么

TagLauncher 启动后,用户看不到右上角菜单栏里的 TagLauncher 图标,容易误判为 TagLauncher 没有启动、菜单栏逻辑坏了,或者 App 不稳定。

这次排查后确认:表层原因是本机安装了 THAW。THAW 是一个菜单栏图标管理软件,它会把菜单栏图标分到 visiblehiddenalwaysHidden 等区域。当 THAW 把 TagLauncher 图标放入隐藏区或始终隐藏区时,用户看到的现象就是“TagLauncher 菜单栏图标找不到了”。

我们最初的误判风险

这个问题很容易被误判成 TagLauncher 自己的问题,因为现象发生在 TagLauncher 启动后,而且菜单栏图标是 TagLauncher 自己创建的。

但正确排查顺序应先区分两件事:

  • TagLauncher 是否真的没有创建 NSStatusItem
  • TagLauncher 创建了 NSStatusItem,但被第三方菜单栏管理工具移动或隐藏。

如果不做这个区分,很容易在 TagLauncher 菜单栏代码里反复改动,反而增加发布风险。

THAW 的识别逻辑

THAW 不是按用户看到的 App 名称来管理图标,而是按菜单栏项的稳定身份来识别和恢复位置。

从 THAW 源码与本机偏好数据看,它会维护这些关键状态:

  • MenuBarItemManager.knownItemIdentifiers
  • MenuBarItemManager.savedSectionOrder
  • MenuBarItemManager.pinnedHiddenBundleIDs
  • MenuBarItemManager.pinnedAlwaysHiddenBundleIDs
  • NewItemsSection

THAW 的菜单栏项身份大体是 namespace:title 这种形式。对普通 App 来说,namespace 通常来自 bundle id,title 则来自菜单栏 item 的 title / autosaveName / 系统可见标题等信息。源码里的 MenuBarItemTag.tagIdentifier 也体现了这种思路:使用 namespace:title,必要时加 instance index,用来跨 window id 变化维持识别。

所以,THAW 判断一个图标是不是“同一个图标”,依赖的是稳定的底层身份,而不是图标长什么样、App 中文名是什么、用户以为什么名字。

本机这次的根因

这台机器上的 THAW 偏好里残留了 TagLauncher 多个历史身份:

  • 旧 bundle id:com.apptag.launcher
  • 新 bundle id:com.taglauncher.app
  • 旧的不稳定菜单栏项名:Item-0
  • 系统克隆项:System Status Item Clone
  • 当前稳定项:com.taglauncher.app:com.taglauncher.app.statusItem

同时,THAW 的状态里还存在两个关键条件:

  • NewItemsSection = alwaysHidden
  • pinnedHiddenBundleIDs / pinnedAlwaysHiddenBundleIDs 中包含旧的 com.apptag.launcher

这意味着:当测试环境里反复安装、替换、启动不同历史版本时,THAW 可能把 TagLauncher 识别成旧图标、新图标、迁移后的图标或新出现图标,并根据历史布局或“新图标默认 alwaysHidden”的配置把它隐藏起来。

因此,这次问题的根本解释是:

TagLauncher 的菜单栏图标身份曾经历过 bundle id 和 status item 标识变化,THAW 又会持久化这些身份和隐藏区归属。本机 THAW 留下了历史污染状态,导致当前 TagLauncher 即使已经创建菜单栏图标,也会被 THAW 按旧规则或新图标规则放进隐藏区。

我们已经做过的 TagLauncher 侧修复

历史上已经针对 THAW 类工具做过一次关键修复,核心是让菜单栏图标身份稳定。

当前 TagLauncher 应保持这些规则:

  • NSStatusItem.autosaveName 必须稳定。
  • autosaveName 应随当前正式 bundle id 派生,例如 com.taglauncher.app.statusItem
  • setupMenuBar() 重复执行时应复用已有 NSStatusItem,不要无故 remove 再重新创建。
  • 菜单栏按钮应有稳定的 identifier 和 accessibility 标识。
  • 语言刷新、数据刷新、窗口状态变化不应导致菜单栏 status item 被重建。

当前代码已经符合这个方向:AppIdentity.statusItemAutosaveName 使用当前 bundle id 派生,setupMenuBar()statusItem == nil 时才创建,并设置稳定 autosaveName、button identifier 和 accessibility identifier。

所以这次不能简单说是 TagLauncher 新版本又把菜单栏代码写坏了。更准确的判断是:TagLauncher 侧的稳定化修复仍在,但本机 THAW 的旧状态会继续影响测试结果。

解决方式

产品代码侧

如果当前代码仍满足以下条件,原则上不需要为这次 THAW 隐藏现象再改 TagLauncher:

  • 当前正式 bundle id 稳定为 com.taglauncher.app
  • 当前 status item autosaveName 稳定为 com.taglauncher.app.statusItem
  • 启动后会设置 statusItem.isVisible = true
  • setupMenuBar() 不会反复销毁重建 status item。

这类情况下,继续改代码的收益很低,风险反而在于破坏已经稳定的菜单栏身份。

测试机器侧

对这台测试机器,应该清理或修正 THAW 的 TagLauncher 历史状态。

优先使用 THAW UI:

  • 找到 TagLauncher 或疑似 TagLauncher 的图标项。
  • hidden / alwaysHidden 移回 visible
  • 检查 THAW 的“新图标默认位置”,不要在测试 TagLauncher 时设为 alwaysHidden
  • 退出并重启 THAW,再启动 TagLauncher 验证。

如需手工处理偏好,必须先备份 THAW 偏好文件,再只清理 TagLauncher 相关记录,不要直接清空 THAW 全部配置,因为那会破坏用户自己的菜单栏布局。

需要关注的键:

defaults read com.stonerl.Thaw 2>&1 | rg -n -C 3 'taglauncher|apptag|NewItemsSection|pinnedHidden|pinnedAlways|savedSectionOrder|knownItemIdentifiers' | head -c 24000

目标是移除或修正这些历史项:

  • com.apptag.launcher:*
  • com.taglauncher.app:System Status Item Clone
  • com.taglauncher.app:Item-0
  • 被放在 hidden / alwaysHidden 中的 TagLauncher 项

保留或恢复当前稳定项:

  • com.taglauncher.app:com.taglauncher.app.statusItem

后续排查标准

以后如果再次出现“TagLauncher 菜单栏图标不见了”,按这个顺序排查:

  1. 确认 TagLauncher 进程是否存在。
  2. 确认当前安装包版本和 bundle id。
  3. 确认代码是否仍设置稳定 NSStatusItem.autosaveName
  4. 检查是否有 THAW、Bartender、Ice 等菜单栏管理工具正在运行。
  5. 检查这些工具是否把 TagLauncher 放进 hidden / alwaysHidden。
  6. 检查是否存在旧 bundle id、Item-0System Status Item Clone 等历史身份残留。
  7. 只有确认第三方工具没有隐藏、且 TagLauncher 自己没有创建 status item 时,才进入 TagLauncher 菜单栏代码修复。

以后开发要遵守的规则

  • 不要随意改 TagLauncher 的正式 bundle id。
  • 不要随意改菜单栏 autosaveName
  • 不要让菜单栏图标在刷新配置、刷新语言、刷新数据时重建。
  • 不要把 removeStatusItem 当作普通刷新手段。
  • 测试菜单栏问题时,要同时覆盖干净环境和安装了 THAW / Bartender / Ice 的污染环境。
  • 如果测试机长期装过多个历史版本,应把第三方菜单栏工具的历史状态视为变量,而不是默认认为 App 代码有问题。

当前结论

这次 THAW 隐藏 TagLauncher 图标,更像是测试机器上的 THAW 历史状态与 TagLauncher 历史身份迁移叠加造成的问题,不是当前 TagLauncher 必须通过代码修复的新回归。

产品侧已经有通用修复方向:稳定 status item 身份并复用同一个 NSStatusItem。测试侧需要清理 THAW 对旧 TagLauncher 身份的记忆,或至少把当前稳定项 com.taglauncher.app:com.taglauncher.app.statusItem 放回 visible。