平台说明 - iOS
部署
使用macOS上的Qt Creator可以开发、构建、运行和调试适用于iOS的Qt应用程序。工具链由Apple的Xcode提供,对于目标为iOS的项目,在项目上运行qmake或CMake也会生成一个Xcode项目文件(.xcodeproj),包括初始应用程序设置。由于Qt Creator不提供管理iOS平台特定所有设置的界面,有时需要直接在Xcode中进行调整。在提交应用程序到Apple的App Store发布之前,检查应用程序是否正确配置尤为重要。
应用程序包
iOS应用程序通常作为自包含的应用程序包进行部署。应用程序包包含应用程序的可执行文件以及依赖项,例如Qt库、插件、翻译和其他应用程序可能需要的资源。
要使用CMake将应用程序构建为应用程序包,在您的可执行目标上设置MACOSX_BUNDLE
属性,如下所示
qt_add_executable(app) if(APPLE) set_target_properties(tst_manual_ios_assets PROPERTIES MACOSX_BUNDLE TRUE) endif()
使用qmake,应用程序包是默认的。要禁用它,请在您的项目文件(.pro
)中设置CONFIG -= app_bundle
。
信息属性列表文件
在iOS和macOS上,信息属性列表文件(Info.plist)用于配置应用程序包。这些配置设置包括
- 应用程序显示名称和标识符
- 必需的设备功能
- 支持的用户界面方向
- 图标和启动图片
有关详细信息,请参阅iOS开发库中信息属性列表文件的文档。
CMake中的Info.plist
CMake会为目标具有其MACOSX_BUNDLE
属性设置为TRUE
的目标生成一个默认的Info.plist
文件。不幸的是,该文件不适合iOS项目。
相反,项目可以使用qt_add_executable,该命令将自动生成一个带有适用于iOS项目的默认值的Info.plist
文件。
要指定一个自定义的Info.plist
,项目可以将MACOSX_BUNDLE_INFO_PLIST
目标属性设置为如下所示。这样做将禁用qt_add_executable提供的自动文件生成,并将使用CMake为项目提供的Info.plist
文件的原生处理。
qt_add_executable(app) if(IOS) set_target_properties(app PROPERTIES MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/ios/Info.plist") endif()
有关CMake为CMake完成的模板替换指定的目标属性和变量信息,请参阅CMake MACOSX_BUNDLE_INFO_PLIST文档。
QMake中的Info.plist
当运行 qmake 时,会生成一个带有合适默认值的 Info.plist
文件。
建议用您的副本替换生成的 Info.plist,以防止在下次运行 qmake 时被覆盖。您可以在 .pro 文件中使用 QMAKE_INFO_PLIST 变量定义自定义信息属性列表。
ios { QMAKE_INFO_PLIST = ios/Info.plist }
应用资源
对于无法打包到 Qt 资源中的文件,QMAKE_BUNDLE_DATA qmake 变量提供了一种指定要复制到应用程序包中的一组文件的方法。例如
ios { fontFiles.files = $$files(fonts/*.ttf) fontFiles.path = fonts QMAKE_BUNDLE_DATA += fontFiles }
使用 CMake,可以以下方式完成相同的操作
qt_add_executable(app) file(GLOB_RECURSE font_files CONFIGURE_DEPENDS "fonts/*.ttf") if(IOS AND font_files) target_sources(app PRIVATE ${font_files}) set_source_files_properties( ${font_files} PROPERTIES MACOSX_PACKAGE_LOCATION Resources/fonts) endif()
对于图像资源,可以使用 Xcode中的资源目录作为替代方案,可以使用以下方式用 qmake添加:
ios { QMAKE_ASSET_CATALOGS += ios/Assets.xcassets }
使用 CMake
qt_add_executable(app) set(asset_catalog_path "ios/Assets.xcassets") target_sources(app PRIVATE "${asset_catalog_path}") set_source_files_properties( ${asset_catalog_path} PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
图标
从 Xcode 13 开始,图标需要添加到图标集的资产目录中,通常称为 AppIcon
。然后 Xcode 会负责更新 Info.plist
文件,添加正确的键和值,以及将任何必要的图标文件直接复制到应用程序包中。
从 Xcode 14 开始,只需要一个 1024x1024 像素的图像,Xcode 会从它生成所有必要的图标。也可以在资产目录中手动指定图像。
可以指定图标的详细列表在图标文件中查看。
文件名不重要,重要的是像素大小。为了支持通用 iOS 应用程序,需要以下图像
- [email protected]: 120 x 120 (用于 iPhone)
- AppIcon76x76@2x~ipad.png: 152 x 152 (用于 iPad)
- AppIcon167x167.png: 167x167 (用于 iPad Pro)
- AppIcon1024x1024.png: 1024 x 1024 (用于 App Store)
临时分发还应包括以下文件名在应用程序包中,以便在 iTunes中显示应用程序
- iTunesArtwork 512x512
- iTunesArtwork@2x 1024x1024
添加图标最简单的方法是按照创建资产目录和集中的 Xcode 文档进行。
当使用 CMake 构建项目时,也应该指定以下 Xcode 特性,以确保 Xcode 生成应用程序图标。
set_target_properties(app_target_name PROPERTIES XCODE_ATTRIBUTE_ASSETCATALOG_COMPILER_APPICON_NAME AppIcon)
以下是一个 Xcode 14 的 Assets.xcassets/AppIcon.appiconset/Contents.json
文件的例子:
{ "images" : [ { "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "20x20" }, { "idiom" : "universal", "platform" : "ios", "scale" : "3x", "size" : "20x20" }, { "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "29x29" }, { "idiom" : "universal", "platform" : "ios", "scale" : "3x", "size" : "29x29" }, { "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "38x38" }, { "idiom" : "universal", "platform" : "ios", "scale" : "3x", "size" : "38x38" }, { "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "40x40" }, { "idiom" : "universal", "platform" : "ios", "scale" : "3x", "size" : "40x40" }, { "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "60x60" }, { "idiom" : "universal", "platform" : "ios", "scale" : "3x", "size" : "60x60" }, { "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "64x64" }, { "idiom" : "universal", "platform" : "ios", "scale" : "3x", "size" : "64x64" }, { "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "68x68" }, { "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "76x76" }, { "idiom" : "universal", "platform" : "ios", "scale" : "2x", "size" : "83.5x83.5" }, { "filename" : "AppIcon1024x1024.png", "idiom" : "universal", "platform" : "ios", "size" : "1024x1024" } ], "info" : { "author" : "xcode", "version" : 1 } }
启动屏幕和启动图像
启动屏幕
每个iOS应用程序都必须提供一个启动屏幕,在应用程序启动时显示。启动屏幕是一个界面构建器 .xib
文件,也称为故事板文件。有关更多信息,请参阅 指定您应用启动屏幕。
启动屏幕支持是在 iOS 9.0 中引入的。
qmake 和 CMake 都生成一个名为 LaunchScreen.storyboard
的默认启动屏幕。
要指定自定义启动屏幕,必须将其复制到应用程序包中,并将 UILaunchStoryboardName
键设置为 Info.plist
文件中的启动屏幕名称。
从 Qt 6.4 开始,Qt 支持 CMake 的自定义启动屏幕,从 Qt 6.0 开始支持 qmake。
假设启动文件名为 Launch.storyboard
,可以按以下方式添加到 Info.plist
中:
<key>UILaunchStoryboardName</key> <string>Launch</string>
使用以下代码片段将启动屏幕复制到应用程序包中,使用 qmake:
ios { QMAKE_IOS_LAUNCH_SCREEN = $$PWD/Launch.storyboard }
使用 CMake
qt_add_executable(app) if(IOS) set_target_properties(app PROPERTIES QT_IOS_LAUNCH_SCREEN "${CMAKE_CURRENT_SOURCE_DIR}/Launch.storyboard") endif()
启动图像
还可以指定启动图片(PNG文件)而不是启动屏幕。
注意: 使用启动图片不建议,因为自iOS 13.0起就不再支持它们。请考虑改为使用启动屏幕。
启动图片需要复制到应用包中,并在Info.plist
文件中使用UILaunchImages
键设置其名称。
以下图片需要准备:
- [email protected]: 640 x 1136
- LaunchImage-iOS7-Landscape.png: 1024 x 768
- [email protected]: 2048 x 1536
- LaunchImage-iOS7-Portrait.png: 768 x 1024
- [email protected]: 1536 x 2048
- [email protected]: 640 x 960
可以将这些图片添加到Info.plist
中,如下所示:
<key>UILaunchImages</key> <array> <dict> <key>UILaunchImageMinimumOSVersion</key> <string>7.0</string> <key>UILaunchImageName</key> <string>LaunchImage-iOS7</string> <key>UILaunchImageOrientation</key> <string>Portrait</string> <key>UILaunchImageSize</key> <string>{320, 568}</string> </dict> <dict> <key>UILaunchImageMinimumOSVersion</key> <string>7.0</string> <key>UILaunchImageName</key> <string>LaunchImage-iOS7</string> <key>UILaunchImageOrientation</key> <string>Portrait</string> <key>UILaunchImageSize</key> <string>{320, 480}</string> </dict> </array> <key>UILaunchImages~ipad</key> <array> <dict> <key>UILaunchImageMinimumOSVersion</key> <string>7.0</string> <key>UILaunchImageName</key> <string>LaunchImage-iOS7-Landscape</string> <key>UILaunchImageOrientation</key> <string>Landscape</string> <key>UILaunchImageSize</key> <string>{768, 1024}</string> </dict> <dict> <key>UILaunchImageMinimumOSVersion</key> <string>7.0</string> <key>UILaunchImageName</key> <string>LaunchImage-iOS7-Portrait</string> <key>UILaunchImageOrientation</key> <string>Portrait</string> <key>UILaunchImageSize</key> <string>{768, 1024}</string> </dict> <dict> <key>UILaunchImageMinimumOSVersion</key> <string>7.0</string> <key>UILaunchImageName</key> <string>LaunchImage-iOS7</string> <key>UILaunchImageOrientation</key> <string>Portrait</string> <key>UILaunchImageSize</key> <string>{320, 568}</string> </dict> <dict> <key>UILaunchImageMinimumOSVersion</key> <string>7.0</string> <key>UILaunchImageName</key> <string>LaunchImage-iOS7</string> <key>UILaunchImageOrientation</key> <string>Portrait</string> <key>UILaunchImageSize</key> <string>{320, 480}</string> </dict> </array>
要使用qmake将启动图片复制到应用包中,请在项目的.pro文件中使用以下代码片段:
ios { app_launch_images.files = $$files($$PWD/ios/LaunchImage*.png) QMAKE_BUNDLE_DATA += app_launch_images }
使用 CMake
qt_add_executable(app) file(GLOB_RECURSE launch_images CONFIGURE_DEPENDS "ios/LaunchImage*.png") if(IOS AND launch_images) target_sources(app PRIVATE ${launch_images}) set_source_files_properties( ${launch_images} PROPERTIES MACOSX_PACKAGE_LOCATION Resources) endif()
注意:早期的iOS版本支持在Info.plist
中使用UILaunchImageFile
键指定单个启动图片,但自iOS 10.0起,对该功能的支持已被弃用。
原生图片选择器
如果您的Info.plist
文件中包含NSPhotoLibraryUsageDescription
条目,qmake将自动包含一个额外的插件,该插件可以启用对原生动图选择器的访问。如果您的QFileDialog目录设置为
QStandardPaths::standardLocations(QStandardPaths::PicturesLocation).last();
或 alternately,在QML中的FileDialog目录设置为
shortcuts.pictures
那么将显示原生图片选择器,允许访问用户的相册。
表达支持的iOS版本
Apple平台有一个内置方式来表达应用程序支持的操作系统版本,它可以自动显示针对较老版本的友好的错误信息,提示用户更新OS,而不是崩溃和显示堆栈跟踪。
在表达对特定范围内的OS版本支持中所涉及的主要概念有:
- 部署目标指定了您应用支持的最低的macOS或iOS版本。
- SDK版本指定了您应用支持的最高的macOS或iOS版本。
当您为Apple平台开发应用程序时,您应始终使用最新版本的Xcode以及开发当时的最新SDK。在某些平台上,如iOS,如果不行,您实际上会被App Store拒绝。因此,SDK版本始终大于或等于部署目标。
当您为Apple平台开发应用程序时,您必须设置部署目标。Xcode工具链中的各种构建工具都有您可以使用来设置此值的标志,包括但不限于编译器和链接器。通过设置部署目标值,您明确表示您的应用程序至少必须在该版本上运行,且不会与OS的任何更早版本一起工作。然后,您需要确保您对系统API的使用与您所声明的相匹配。由于编译器知道您已声明的内容,它可以帮助确保这一点。
SDK版本被认为是一个与OS兼容的软最大版本。这意味着如果应用是用SDK构建的,即使是在更高版本的OS上,它也会继续使用该SDK的行为,因为操作系统会检查二进制的加载命令,并以向后兼容的方式模拟旧版OS。例如,如果应用是用macOS 10.12 SDK构建的,那么即便是在10.13及以上版本上,它也会继续使用10.12的行为。
然而,Mach-O二进制文件天生就是向前兼容的。例如,使用iOS 9 SDK构建的应用在iOS 10上运行良好,但在新版本中可能不会采用对某些功能所做的行为变更,除非该应用重新编译以针对更新后的SDK。
最低OS版本可以通过编译器和链接器标志表示,这些标志将其嵌入到Mach-O二进制文件中。此外,必须在应用的app bundle中设置LSMinimumSystemVersion
键。此值必须与传递给编译器和链接器的值相同,因为在macOS上它将允许操作系统显示一个友好的错误对话框,表明该应用需要更高版本的操作系统,而不是崩溃对话框。《LSMinimumSystemVersion
》也是App Store使用来显示所需OS版本的键;编译器和链接器标志在那里没有任何作用。
大多数情况下,Qt应用将没有问题运行。例如,在qmake中,Qt mkspecs会设置QMAKE_IOS_DEPLOYMENT_TARGET或QMAKE_MACOSX_DEPLOYMENT_TARGET到Qt本身支持的最低版本。同样,在Qbs中,Qt模块设置cpp.minimumIosVersion
、cpp.minimumMacosVersion
、cpp.minimumTvosVersion
或cpp.minimumWatchosVersion
到Qt本身支持的最低版本。
然而,在手动设置自己的目标版本时,您必须小心处理。如果您设置的值高于Qt的需求并提供了自己的Info.plist
文件,您必须将一个匹配部署目标的LSMinimumSystemVersion
条目添加到Info.plist
中,因为操作系统会将LSMinimumSystemVersion
值作为权威值使用。
如果您指定的部署目标值低于Qt的要求,则在使用Qt不支持的老版本运行时,应用几乎肯定会在Qt库的某个位置崩溃。因此,请确保实际的构建系统代码反映了实际所需的最低OS版本。
向Apple App Store发布
如下所述,可以验证您的Qt iOS应用是否已准备好发布到App Store:详情请参阅提交应用。要提交应用,您可以使用Xcode或应用加载器(由Xcode安装)。Qt Creator不支持管理Xcode项目配置中所有设置的界面。
应用应在它目标支持的iOS版本和设备上进行测试。Qt应用的最低部署目标因Qt版本而异。更多信息,请参阅支持配置。
实际的发布过程包括创建分发证书和配置文件,创建应用的签名存档,并在其上运行一系列验证测试。
有关更详细的信息,请参阅iOS开发者库中的应用发布指南。
符号可见性警告
在链接 C++ 库的上下文中,函数和对象被称为符号。符号可以是 默认
或 隐藏
的 可见性。
出于性能原因,Qt 以及许多其他库默认使用 隐藏
可见性进行源代码编译,并且只在它们打算在用户项目中使用时标记符号为 默认
可见性。
不幸的是,当某一库使用 隐藏
可见性进行编译,而用户项目应用或库使用 默认
可见性进行编译时,Apple 链接器可能会发出警告。
如果项目开发者想要消除该警告,他们需要将项目代码也编译为 隐藏
可见性。
在 CMake 中,可以通过将以下代码添加到您的 CMakeLists.txt
文件中来实现。
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
在 qmake 中,可以通过将以下代码添加到您的 .pro
文件中来实现。
CONFIG+=hide_symbols
如果项目构建库,任何打算在另一个库或应用中使用库中的符号都需要显式标记为 默认
可见性。例如,可以通过对这样的函数或类使用 Q_DECL_EXPORT 进行注释来实现。
CMake 中的产品存档问题
由于 CMake 中的问题,尝试使用 iOS 应用创建产品存档可能会失败。
当尝试使用 Xcode 的产品 -> 存档菜单项创建存档,或者从命令行使用 xcodebuild -archivePath
时,都可能发生这种情况。
错误信息可能引用未定义的符号或不存在的文件路径。
为了解决这个问题,在尝试创建存档之前,请确保构建项目的 发布
版本。
© 2024 The Qt Company Ltd。本文件内包含的文档贡献的版权归其各自的拥有者。本文件内提供的文档是根据免费软件基金会发布的 GNU 自由文档许可证 1.3 版本 的条款许可的。Qt 及其相关标志是芬兰的 The Qt Company Ltd. 和/或世界上其他国家的商标。所有其他商标均为各自所有者的财产。