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. 发现旧副本后,再处理注册记录
如果查询结果中确实有不再使用的旧副本,按以下步骤处理:
- 停止 Xcode 调试,退出 WidgetKit Simulator。
- 如果已添加过该 widget,先从桌面或通知中心移除。
- 注销确认无用的旧扩展,再移除对应的旧
.app。 - 重新构建并运行当前项目,再次查询注册记录。
注销时使用 .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 后,确认最新扩展能够运行,且日志中不再出现对应的失败信息,才能判断修复是否有效。
备注:内容仅供参考。
