PAYATHON 2026

Xcode 中 macOS widget 构建成功但运行失败,如何修复?

排障赵师傅

结论

先检查原 bundle identifier 对应的扩展注册记录、旧应用副本和 Xcode 运行配置。修改 bundle identifier 后恢复正常,可以帮助缩小排查范围,但还不足以证明缓存损坏。

目前缺少附件中的完整错误信息,无法确定具体原因,也不能据此认定这是 macOS 27 的已知问题。已经清理过 Derived Data,下一步应确认系统实际加载了哪个 widget 扩展,再根据结果处理。

为什么换项目文件夹没有用,换 bundle identifier 却有用?

系统识别应用主要不靠项目名或项目目录。Xcode 模板会根据组织标识和产品名称生成默认 bundle identifier,因此同名新项目即使放在其他目录,也可能沿用原来的标识。Apple:设置 bundle ID

主应用和 widget 扩展各有自己的标识:

  • 主应用,例如 com.example.ABC。
  • widget 扩展,例如 com.example.ABC.ABCWidget。

检查时记录两者的实际值,并确认此前改动的是哪一个。

构建成功说明编译和构建流程已经通过。运行 widget 时,系统还需要发现、加载扩展并生成其内容,这些环节仍可能失败。删除 Derived Data 不会同时重置所有系统扩展注册记录,删除应用容器也不等于注销扩展。

更换 bundle identifier 会改变应用或扩展的身份,还可能影响所用的数据容器和签名配置。可以用它做对照实验,但不能仅凭这一结果判断根因。

1. 先获取完整运行错误

保留原 bundle identifier,复现一次问题,记录以下信息:

  • WidgetKit Simulator 的完整错误,包括错误域、错误码和底层错误。
  • Xcode 控制台中失败前后的输出。
  • macOS 和 Xcode 的具体版本、构建号,以及是否使用测试版。

打开 macOS 的“控制台”(Console.app),选择当前 Mac,开始日志流,再按 widget 扩展的进程名筛选。Apple 工程师也建议从扩展进程的系统日志查起。Apple 开发者论坛:WidgetKit 扩展调试

也可以在终端观察日志,将以下名称替换为实际值:

log stream --style compact --level debug \
  --predicate 'process == "ABCWidgetExtension" OR eventMessage CONTAINS[c] "com.example.ABC.ABCWidget"'

重点查找失败时的路径、签名或权限错误,以及扩展崩溃信息。如果扩展启动后崩溃,就根据崩溃堆栈检查代码;如果系统始终找不到扩展,则先检查注册和嵌入配置。

2. 查询原标识是否对应多个扩展副本

用 macOS 的 pluginkit 可以查询当前用户的扩展注册记录。查询时使用 widget 扩展的 bundle identifier,不要填主应用的标识:

pluginkit -m -A -D -vv -i com.example.ABC.ABCWidget

-m 用于查询注册记录,-A 包含不同版本,-D 包含同一扩展的多个物理副本,-vv 显示详细信息。具体参数说明可通过 man pluginkit 查看。

检查输出中的 .appex 路径,看看是否有:

  • 以前项目目录中的构建产物。
  • /Applications 或 ~/Applications 中安装过的旧应用。
  • 其他测试目录中的同标识应用。
  • 已经失效的路径。

查到多条记录不一定说明有故障,还要结合日志判断失败时是否加载了旧路径。输出中的 ! 表示供调试器使用,不能单凭这个符号认定扩展损坏。

如果没有查询结果,先确认标识填写正确,再检查最新构建的主应用中是否包含以下扩展,名称以实际构建产物为准:

ABC.app/Contents/PlugIns/ABCWidgetExtension.appex

3. 发现旧副本后,再处理注册记录

如果查询结果中确实有不再使用的旧副本,按以下步骤处理:

  1. 停止 Xcode 调试,退出 WidgetKit Simulator。
  2. 如果已添加过该 widget,先从桌面或通知中心移除。
  3. 注销确认无用的旧扩展,再移除对应的旧 .app。
  4. 重新构建并运行当前项目,再次查询注册记录。

注销时使用 .appex 的完整路径:

pluginkit -r "/absolute/path/to/OldABC.app/Contents/PlugIns/ABCWidgetExtension.appex"

如果系统仍未发现最新扩展,可以尝试显式注册当前构建产物:

pluginkit -a "/absolute/path/to/ABC.app/Contents/PlugIns/ABCWidgetExtension.appex"

这些路径都是占位示例。可以在 Xcode 的 Products 中找到构建产物,通过 Show in Finder 确认实际位置。

pluginkit -r 和 -a 只能作为开发调试时的有限干预手段。只要旧应用还在系统可发现的位置,扩展就可能再次自动注册;手动注册成功也不保证 WidgetKit 能正常加载它。

处理后仍然失败,可以重启 Mac,再用原标识测试。不要把删除整个扩展数据库或重置全部 Launch Services 当作常规修复步骤。

4. 核对 scheme、扩展标识和签名

在 Xcode 中选择 widget 扩展对应的 scheme,将运行目标设为 My Mac,再执行 Product > Run。Apple 文档说明,这套 Mac widget 调试流程会打开 WidgetKit Simulator。Apple:Debugging widgets

在 Edit Scheme > Run > Arguments 中检查环境变量。如果设置了 _XCWidgetKind,其值必须与代码中 widget configuration 使用的 kind 完全一致。这里填写的是 widget 的 kind,不是 bundle identifier。也要检查旧 scheme 是否还在引用重命名前的值。

接着检查主应用和扩展 target:

  • PRODUCT_BUNDLE_IDENTIFIER 是否分别为预期值,当前构建配置是否覆盖了这些值。
  • 主应用是否嵌入了最新的 .appex。
  • Signing & Capabilities 是否有错误,开发团队配置是否符合预期。
  • 如果使用 App Groups,两个 target 是否启用了需要共享的同一组。

不要为了排查而给基础示例随意添加 App Groups,或关闭沙盒和签名检查。

如果日志指向签名问题,可以检查实际构建产物:

codesign --verify --strict --verbose=4 \
  "/absolute/path/to/ABC.app/Contents/PlugIns/ABCWidgetExtension.appex"

codesign --verify --strict --verbose=4 \
  "/absolute/path/to/ABC.app"

签名检查通过只能排除部分问题。如果检查失败,应回到 Xcode 修正签名配置并重新构建。Apple 的签名排查资料也使用 codesign 检查签名有效性。Apple:排查签名问题

5. 原标识仍失败时,如何继续定位?

保留一个最小复现项目,用同一份代码分别测试原标识和新标识,每次只改变一个变量。然后在新的 macOS 用户账户中测试原标识:

  • 如果新账户正常,继续检查原账户下的注册记录、偏好或应用数据。
  • 如果新账户也失败,问题就还没有被隔离到原账户,需要继续检查项目配置、签名和工具链。
  • 如果实际添加 widget 后能正常使用,只有 WidgetKit Simulator 失败,应重点检查调试 scheme 和 Simulator 的错误日志。

更换 bundle identifier 可以暂时恢复开发,但已发布应用不能随意用新标识替代原标识。如果最小项目仍能稳定复现问题,应通过 Feedback Assistant 提交项目、完整日志、版本与构建号,并写清楚“原标识失败、新标识成功”的对照步骤。

注意事项

不建议继续批量删除 Library/Containers 或 Library/Group Containers。这些目录可能保存应用数据,App Group 容器还可能由多个目标共享,删除它们未必能解决扩展注册问题。

恢复原 bundle identifier 后,确认最新扩展能够运行,且日志中不再出现对应的失败信息,才能判断修复是否有效。

备注:内容仅供参考。