Skip to main content

Python 移动应用开发:将 PySide6 带到 iOS

评论

从 Qt 6.12 起,用 Python 开发移动应用终于覆盖到了 iOS。PySide6 开发者沿用现有的 Android 与桌面端代码,就能直接发布原生 iOS 应用既不用 Swift 或 Objective-C 重写,也不用再维护第二套需要同步的代码。

自 Qt 6.5 让 PySide6 应用跑上 Android 之后,大家自然会追问:那 iOS 呢?iOS 的难点和 Android 完全不是一回事,但从 Qt 6.12 开始,Python 开发者不必为了把应用发布到 iPhone 和 iPad 而改用其他工具链,留在 PySide6 生态里就能完成。

能用 Python 开发 iOS 应用吗?

可以 🎉。从 Qt 6.12 起,PySide6 应用已经能在 iOS 上原生运行。为 iOS 交叉编译 PySide6 会得到一组静态 .a 库,它们会连同 Qt 自带的静态框架、以及 BeeWarePython.xcframework ,一起直接链接进应用的 Xcode 工程(在正式提供 iOS 支持的 Python 3.15 发布之前,都沿用这个方案)。这样一来,所有内容最终都打包进同一个应用二进制文件,而不是在运行时动态加载。

iOS 为什么不能沿用 Android 的做法?

iOS 要求把 Qt 静态链接进应用二进制文件。面向 iOS 的 Qt 是以静态库形式发布的,而不是动态库(.dylib)。如果 PySide6 模块按动态文件加载,Qt 的符号就会出现两份,加载时会直接报重复符号错误。

解决办法是:把每个 PySide6 模块都静态链接进二进制文件,并在 Py_Initialize 之前预先注册到 Python 解释器中。

Qt 是如何接管 iOS 应用生命周期的?

iOS 应用由 UIApplicationMain 驱动,它会接管整个进程并且永不返回。Qt 的 iOS 平台插件提供了 qt_main_wrapper,用 Qt 自己的 application delegate 去调用 UIApplicationMain,从而让完整的 Qt 平台集成生效——包括信号与槽机制和事件循环。再通过设置 Xcode 的 LD_ENTRY_POINT 构建设置,Qt 就能从进程启动那一刻起掌握控制权。

之后,Qt 的运行循环集成(run loop integration)会把控制权交回给 main(),由它初始化 Python 并运行应用脚本。

怎样让 PySide6 应用跑在 iPhone 或 iPad 上?

把 PySide6 应用跑到 iOS 上一共三步:每个 Qt 版本交叉编译一次 PySide6,在配置文件里写清楚应用信息,然后生成并构建 Xcode 工程。

第一步 · 交叉编译 PySide6

python pyside-setup/tools/cross_compile_ios/main.py build --qt-install-path ~/Qt/6.12.0

这条命令会下载 Python.xcframework,生成 CMake 工具链文件,并针对 ios_arm64 交叉编译 shiboken6PySide6,产出静态库。

这一步每个 Qt 版本只需执行一次,产物可以在您所有的 iOS 应用中复用。

第二步 · 描述应用信息

生成 Xcode 工程需要一个 pyside6-ios.toml 文件,里面写明配置工程所需的信息。目前这个文件要手动编写,从现有 PySide6 项目自动生成的功能正在开发中。

[app]
name = "My PySide6 App"
bundle-id = "com.example.mypyside6app"
output-dir = "generated"

[pyside6]
modules = ["QtCore", "QtGui", "QtWidgets"]

[python]
version = "3.14"
scripts = ["scripts/main.py"]

[signing]
style = "Automatic"

第三步 · 生成并构建 Xcode 工程

python pyside-setup/tools/cross_compile_ios/main.py generate -c pyside6-ios.toml

open generated/MyPySide6App.xcodeproj

这一步会生成:

  • main.mm:初始化 Python,把所有 PySide6 模块注册为内置模块,然后运行 Python 脚本;

  • Info.plist:iOS 应用的元数据;

  • project.pbxproj:链接全部 Qt 框架、PySide6 静态库(.a)、Python.xcframework 和 iOS 系统框架,并设置 LD_ENTRY_POINT

在 Xcode 中选好设备,点击运行 ▶️ 即可。

pyside-ios

1:Xcode 工程(左)与设备截图(右)

一套代码,同时覆盖 Android 与 iOS

PySide6 现在同时支持 Android(Qt 6.5 起)和 iOS(Qt 6.12 起),一套 PySide6 代码就能覆盖这两大主流移动平台。底层的构建与打包方式确实不同——iOS 走静态链接,Android 走动态加载——但应用代码本身不需要为此改动。一个 PySide6 项目,不用重写就能部署到桌面、Android 以及 iOS。

PySide6 在 iOS 上的现有限制

这将是首个包含 iOS 部署支持的版本,因此有几点限制需要提前了解。如果您愿意为其中任何一项提交修复方案,我们很乐意评审:

  • 暂不支持第三方包。带 C 扩展的包(numpyPillow 等)目前无法使用,PyPI 上还没有 iOS 平台的 wheel 包。
  • 暂不支持 iOS 模拟器。目前测试必须使用真机,模拟器支持仍在研究中。
  • Xcode 工程需手动生成。我们计划提供 pyside6-ios-deploy 控制台脚本(对应 Android 端的 pyside6-android-deploy),取代目前“先生成、再打开工程”的手动步骤。
  • 目前依赖 BeeWare 的 Python.xcframework。待 Python 3.15 正式发布后,我们打算切换到 Python 官方的 iOS 支持。

常见问题

能用 Python 开发 iOS 应用吗?

可以。用 PySide6 搭配 Qt 6.12 或更高版本,就能把 Python 应用静态编译成原生 iOS 应用二进制文件,在 iPhone 或 iPad 上运行。前提是为 ios_arm64 交叉编译 PySide6 并生成 Xcode 工程,但应用代码本身就是标准的 PySide6 代码。

除了 PySide6,还有别的方式用 Python 开发 iOS 应用吗?

有。例如 BeeWare 的 Briefcase(PySide6 的 iOS 工具链正是复用了它的 Python.xcframework),以及 kivy-ios。区别在于,PySide6 能提供完整的原生 Qt Widgets 与 QML 工具集。

Python 支持跨平台移动开发吗?

支持。有了 PySide6,同一套代码现在可以同时面向 Android 和 iOS。底层构建流程因平台而异(Android 用动态库加载,iOS 需要静态链接),但应用逻辑和 UI 代码在两个平台上可以共用。

Python 在 iOS 上目前有哪些限制?

眼下主要有三点:带 C 扩展的第三方包还用不了(PyPI 上还没有 iOS 平台的 wheel 包)、不支持 iOS 模拟器、以及 Xcode 工程仍需手动生成,还没有做到一条命令完成部署。这三项都在推进中。

把 PySide6 应用发布到 iOS,需要会 Swift 或 Objective-C 吗?

不需要。生成的 Xcode 工程已经处理好原生 iOS 的入口点和应用生命周期(main.mmInfo.plistLD_ENTRY_POINT)。应用逻辑仍然写在 PySide6 里,Xcode 只负责构建和签名,不用您写原生代码。

去哪里获取 PySide6 上手试用?

相关工具位于 pyside-setup/tools/cross_compile_ios/ 目录下。

本文之外的完整 API 参考,请查阅 Qt for Python 官方文档如果想看看同样的 PySide6 方案在 Android 上是怎么做的,可以参考 Qt for Python on Android:用 pyside6-android-deploy 交叉编译,两边的流程是对应的。

欢迎在 Qt bug tracker 的 PySide 组件下提交反馈、缺陷报告和疑问。

感谢 Patrick Stinson 在让 PySide6 跑上 iOS 这件事上所做的早期探索。我们最终采用的方案和他的并不相同,但那些前期工作为这项进展打下了基础。

 

评论

Subscribe to our blog

Try Qt 6.11 Now!

Download the latest release here: www.qt.io/download

Qt 6.11 is now available, with new features and improvements for application developers and device creators.

We're Hiring

Check out all our open positions here and follow us on Instagram to see what it's like to be #QtPeople.