如何在macOS开发中给 PKG 签名和公证(productsign+notarytool)

macOS 中,给 PKG 文件进行签名是一个确保用户能够顺利无警告地安装软件的重要步骤。以下是给 PKG 签名的详细步骤:

一、准备阶段

获取开发者账号和证书:
  • 首先,需要在苹果开发者网站(Apple Developer)注册一个有效的开发者账号。
  • 登录开发者账号后,进入 “Certificates, IDs & Profiles” 页面。
  • 创建并下载 “Developer ID Application” 证书和 “Developer ID Installer” 证书。这两个证书分别用于签名应用程序和 PKG 安装包。
  • 将下载的证书双击安装到“钥匙串访问”中。
打包PKG文件:
  • 使用 Packages 工具或其他打包工具,将需要分发的应用程序和相关文件打包成一个 PKG 安装包。
  • 在打包过程中,可以添加安装前和安装后的脚本来执行一些自定义操作。

二、签名阶段

获取证书名称:
  • 打开终端,输入命令 security find-identity -v,列出所有已安装的证书。
  • 找到与 “Developer ID Installer” 相关的证书名称,通常格式为 “Developer ID Installer: 开发者名称 (证书标识符)”。
签名PKG文件:

使用 productsign 命令对 PKG 文件进行签名。命令格式如下:

例如:

这将生成一个新的签名后的 PKG 文件。

三、验证签名

验证PKG文件签名:

使用 pkgutil 命令验证 PKG 文件的签名是否有效。命令格式如下:

如果签名有效,命令将输出 “signed by a developer certificate issued by Apple for distribution”。

四、公证阶段(可选)

macOS 10.14.5 开始,苹果要求所有分发的软件都必须经过公证(Notarization)。公证过程如下:

准备已签名的软件包:

在公证之前,你需要确保你的 .pkg 文件已经使用 codesign 命令进行了签名。

将公证凭证存储到 macOS 的钥匙串中:

上传PKG文件到苹果服务器:

使用 notarytool 提交你的软件包进行公证。这一步会将你的软件包上传到 Apple 的公证服务,并启动公证流程。

  • /path/to/your/signed/package.pkg 是你的已签名软件包的路径。
  • --keychain-profile 参数用于指定包含你签名证书的钥匙串配置文件(可选,如果证书在默认钥匙串中则不需要)。
  • --wait 参数告诉 notarytool 等待公证完成并返回结果。

如果公证成功,notarytool 会返回一个 RequestUUID,你可以使用这个 UUID 来查询公证状态或进行后续操作。

检查公证结果(如果未使用 --wait):

如果你没有使用 --wait 参数,你需要使用返回的 RequestUUID 来检查公证状态。

替换 <RequestUUID> 为你实际获得的 UUID

五、盖章步骤

一旦你的软件包通过了公证,你就可以使用 stapler 工具对其进行盖章。

对软件包进行盖章:

使用 stapler 工具对你的软件包进行盖章,以表明它已经通过了 Apple 的公证服务。

/path/to/your/signed/package.pkg 是你的已签名且已公证的软件包的路径。

验证盖章结果(可选):

你可以使用 stapler 工具来验证你的软件包是否已经被正确盖章。

/path/to/your/stapled/package.pkg 是你的已盖章软件包的路径。

如果所有步骤都成功完成,你的软件包现在应该已经准备好分发给用户了。

用户可以通过 macOS 的“安装未知开发者应用”的安全设置来安装你的软件包,而不会因为未经验证的应用程序而被阻止。

六、命令集合

以下是一个简要的流程,以及一个相应的 .sh 脚本示例:

1.用于签名 .pkg  文件( productsign.sh )。

2.用于签名和公证 .pkg 文件(productsign-online-notarytool.sh)。

请注意,这些步骤假设你已经具备了必要的 Apple Developer 账户、证书和配置文件,并且你的 macOS 系统已经安装了 XcodeXcode Command Line Tools。如果你遇到任何问题,请检查你的证书、配置文件和路径是否正确,以及你是否拥有执行这些命令的适当权限。

参考:

https://taoofcoding.tech/blogs/2022-11-13/use-notarytool-to-notary-macos-app

https://blog.csdn.net/Crystal_Mr_Rose/article/details/136351429

macOS 工具 - 查看PKG文件内容, App下载安装 SuspiciousPackage官方下载地址(免费): http://www.mothersruin.com/software/SuspiciousPackage/get.html

Mac OS平台下应用程序PKG安装包制作工具Packages, App下载安装Packages官方下载地址(免费): http://s.sudre.free.fr/Software/Packages/resources.html

参考链接


如何在macOS开发中给 PKG 签名和公证(productsign+notarytool)

Not running swift-stdlib-tool: ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES is enabled, but the product type 'com.apple.product-type.tool' is not a wrapper type.

使用 Xcode 在原有APP项目(.app)新建了一个独立的命令行可执行程序,作为 SMJobBless 使用的独立进程。编译的时候出现如下告警:

原来的项目配置了 ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES 编译选项,所以新建的子工程默认继承了这个编译选项。

根据编译参数文档 Build settings reference,文档对与这个编译参数的说明如下:

明确说明 ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES 编译选项,只针对 .app 项目,不能作用于独立的二进制程序。

原因在于 .app 项目是一个文件夹,可以在 Framework 目录里面存放额外的文件,独立的进程只有一个文件,没有存储独立的 libswift.dylib 的地方。

解决方法很简单,在编译选项中,设备设置为 No 即可。

如下图:

参考链接


macOS磁盘空间不释放(删除文件空间不恢复)

昨天(2025/12/15)把手上的 MacBook Pro M2 版本的系统升级到 macOS Tahoe 26.2 版本之后,发现系统剩余空间只有不到 50GB了,于是手工删除可一些不重要的文件,大约 200GB 的样子。

结果情况不仅没有好转,反倒是更严重了。更匪夷所思的是,文件删除的越多,系统剩余可用空间越少。最后急剧减少到接近为 0, 系统报错存储空间不足,内存不足。

怀疑是 TimeMachine 导致的问题,于是尝试了

也是不起任何作用,其中的一个镜像无论如何都删除不了。

最后发现是 Apple FS 的快照空间占用了这部分空间,很奇怪以前没有发生过类似情况。

怀疑是系统升级设置了回滚快照,防止升级出现问题。

但是系统升级完成后,快照逻辑没有被解除,导致文件越删除磁盘空间越少的诡异问题。

我这边操作删除的时候,这部分快照消耗了大约 400GB 的磁盘空间,删除快照之后,系统卡顿了大约几分钟的样子恢复正常。应该是系统在进行集中磁盘清理导致的锁盘引起卡顿。

  1. 打开"磁盘工具"
  2. 点工具栏的显示-显示APFS快照(或者按键盘command+shift+s)
  3. 下放会出现快照占用空间

参考链接


Mac OS 磁盘空间不释放(删除文件空间不恢复)

‘withUnsafeBytes’ is deprecated: use ‘withUnsafeBytes(_: (UnsafeRawBufferPointer) throws -> R) rethrows -> R’ instead

在编写 Swift 代码的时候,执行如下代码的时候:

出现如下警告:

修正警告的方式,参考使用如下代码:

参考链接


macOS 26 系统如何在聚焦搜索中不显示 iPhone App

在 macOS 26 系统中,Apple 增强了「聚焦搜索」(Spotlight)的功能。如果你启用了 iPhone 镜像,系统会自动将 iPhone 上的应用程序同步到 Mac 的聚焦搜索结果中,方便直接在 Mac 上快速启动或查找。

如下图:

继续阅读macOS 26 系统如何在聚焦搜索中不显示 iPhone App

Flutter桌面端-应用启动后占满屏幕

前置条件

  • MacBook Pro M2 macOS Tahoe (26.0) / Windows 11 24H2
  • Flutter 3.35.3

功能需求

以目前的情况来看,Flutter 的桌面端软件其实跟移动端软件很像,因为 Flutter 桌面端目前默认只有一个窗口,而不是像原生的桌面端软件一样,经常会有很多个窗口。 比较不一样的是,移动端是直接全屏显示,桌面端的软件是以窗口的形式存在的。

而桌面端窗口大小可以设置,还可以由用户自由放大缩小。

所以一般桌面端软件都需要对窗口做一些配置,比如设置启动时的默认窗口大小以达到最佳的界面显示,设置最小的窗口大小来避免界面变形严重或者遮盖了重要界面等等。

我们希望应用启动后就占据整个屏幕,但是不是最大化,顶部状态栏,底部不要进行覆盖,类似 Chrome 浏览器的行为。

解决方法

可以使用 window_manager 插件来实现,但是发现达不到想要的效果。

后面发现 learnFlutter 还有一个开源库是 screen_retriever ,这个插件允许 Flutter 桌面 应用检索关于屏幕大小,显示,光标位置等信息。

试了下确实可以获取到屏幕的高度,可行的实现方式是使用 screen_retriever 获取到屏幕的高度之后再使用window_manager 设置窗口大小。

但是,上述的代码由于需要 Flutter 引擎初始化之后才能执行,因此会短暂先出现小窗口,然后窗口才会变大。整个过程中有明显的延迟,用户体验不好。

因此,还是需要从底层API层面进行窗口大小的调整,应用启动后,窗口大小立即调整完成,用户体验较好。

macOS 解决方案

方案一:

通过调用 NSWindowzoom 函数,实现窗口的放大。代码如下:

方案二:

通过调整 NSWindowvisibleFrame ,实现窗口的放大。代码如下:

方案三(推荐):

调整 MainFlutterWindow 的代码,直接设置窗口大小:

Windows 解决方案

Windows 系统下的解决方案比较简单,直接修改 ShowWindow 函数的参数,设置为 SW_MAXIMIZE 即可。代码如下:

Linux 解决方案

Linux 系统下的使用的是 GTK,因此可以通过在初始化窗口之前调用 gtk_window_maximize 函数即可(此函数支持窗口显示之前调用)。代码如下:

参考链接


Xcode 16 调整 Provisioning Profiles 目录导致证书查不到

cronet demo 使用的 ninja 打包,查找 Provisioning Profiles 路径是 ~/Library/MobileDevice/Provisioning Profiles,但 Xcode 16 把该路径改为了 ~/Library/Developer/Xcode/UserData/Provisioning Profiles,导致在编译 cronetdemo 时找不到证书。

解决办法是把 Xcode 16 的路径下的证书拷贝一份到老的路径 ~/Library/MobileDevice/Provisioning Profiles 即可。

参考链接


Xcode16 调整 Provisioning Profiles 目录导致证书查不到

Mac应用第三方渠道发布指南

1.申请证书

Mac 应用有多种证书,主要包含以下几种:

Apple证书类型
Apple证书类型

  • Apple Development: Xcode 11之后Apple全平台开发证书
  • Apple Distribution: Xcode 11之后Apple全平台发布
  • Mac Development:用来开发和Debug的证书
  • Mac App Distribution:用来给APP文件签名后上传到Mac App Store
  • Mac Installer Distribution:用来给PKG文件签名后上传到Mac App Store
  • Developer ID Installer:用于给PKG文件签名,在非Mac App Store场景使用
  • Developer ID Application:用于给APP文件签名,在非Mac App Store场景使用

继续阅读Mac应用第三方渠道发布指南

解决Mac安装软件的“已损坏,无法打开。 您应该将它移到废纸篓”问题

前置条件

  • macOS Sequoia (15.2) 
  • MacBook Pro 2023-Apple M2 Pro (4能效核、8性能核、32GB内存、2TB磁盘)
  • FreeCAD_weekly-builds-39896-conda-macOS-arm64-py311

问题现象

FreeCAD 下载每周构建版本,则在安装后会报错“已损坏,无法打开。 您应该将它移到废纸篓”,类似下图:

继续阅读解决Mac安装软件的“已损坏,无法打开。 您应该将它移到废纸篓”问题