Developing, building, running, and debugging a Qt for iOS application can all be done with Qt Creator on macOS. The toolchain is provided by Apple's Xcode, and running qmake or CMake on a project targeted for iOS will also generate an Xcode project file (.xcodeproj), with initial application settings. As Qt Creator does not provide an interface for managing all of the settings specific to iOS platform, it is sometimes necessary to adjust them in Xcode directly. Checking that the application is configured correctly is especially important before submitting an application for publishing in Apple's App Store.
iOS applications are typically deployed as self-contained application bundles. The application bundle contains the application's executable as well as dependencies, such as the Qt libraries, plugins, translations, and other resources the application may need.
To build your application as an application bundle with CMake, set the
MACOSX_BUNDLE
property on your executable target, as follows:
qt_add_executable(app) if(APPLE) set_target_properties(tst_manual_ios_assets PROPERTIES MACOSX_BUNDLE TRUE) endif()
With qmake, bundles are the default. Set
CONFIG -= app_bundle
in your project file (
.pro
) to disable it.
Information property list file (Info.plist) on iOS and macOS is used for configuring an application bundle. These configuration settings include:
See the documentation on Information Property List File in iOS Developer Library for details.
CMake generates a default
Info.plist
file if a target has its
MACOSX_BUNDLE
特性被设为
TRUE
. Unfortunately that file is not suitable for iOS projects.
Instead, projects can use
qt_add_executable
, which will automatically generate an
Info.plist
file with default values suitable for iOS projects.
To specify a custom
Info.plist
, projects can set the
MACOSX_BUNDLE_INFO_PLIST
target property as shown below. Doing that will disable the automatic file generation provided by
qt_add_executable
and will instead use CMake's native handling for the project-provided
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 MACOSX_BUNDLE_INFO_PLIST documentation for information on which target properties and variables can be specified for the template substitution performed by CMake.
When qmake is run, an
Info.plist
file is generated with appropriate default values.
It is advisable to replace the generated Info.plist with your own copy, to prevent it from being overwritten the next time qmake is run. You can define a custom information property list with QMAKE_INFO_PLIST variable in your .pro file.
ios { QMAKE_INFO_PLIST = ios/Info.plist }
For files that cannot be bundled into Qt resources, QMAKE_BUNDLE_DATA qmake variable provides a way to specify a set of files to be copied into the application bundle. For example:
ios { fontFiles.files = $$files(fonts/*.ttf) fontFiles.path = fonts QMAKE_BUNDLE_DATA += fontFiles }
With CMake, the same can be done in the following way:
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()
For image resources, an alternative way is to make use of asset catalogs in Xcode, which can be added in the following way with qmake:
ios { QMAKE_ASSET_CATALOGS += ios/Assets.xcassets }
With 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)
Icons need to be set in the
Info.plist
file and then copied to the application bundle. Xcode has special support for icons, but when using Qt, it is usually better to set them in the .pro file or the CMakeLists.txt file.
To support all resolutions and devices, several images should be created. A detailed list of what is required is available at 图标文件 . The filename is not important, but the actual pixel size is. Just a few icons are required. However, to support both iPhone and iPad, the following images are required:
These files should be copied to the application bundle by adding the following code snippet to the project .pro file:
ios { ios_icon.files = $$files($$PWD/ios/AppIcon*.png) QMAKE_BUNDLE_DATA += ios_icon }
With CMake:
qt_add_executable(app) file(GLOB_RECURSE app_icons CONFIGURE_DEPENDS "ios/AppIcon*.png") if(IOS AND app_icons) target_sources(app PRIVATE ${app_icons}) set_source_files_properties( ${app_icons} PROPERTIES MACOSX_PACKAGE_LOCATION Resources) endif()
For the icons to be used, the filenames must also be listed in the
Info.plist
file. The best way is to list all icon files using the
CFBundleIconFiles
key. The iPad specific version can be given using the
CFBundleIcons~ipad
key, by adding the following code snippet to
Info.plist
:
<key>CFBundleIcons</key> <dict> <key>CFBundlePrimaryIcon</key> <dict> <key>CFBundleIconFiles</key> <array> <string>AppIcon29x29.png</string> <string>AppIcon29x29@2x.png</string> <string>AppIcon40x40@2x.png</string> <string>AppIcon57x57.png</string> <string>AppIcon57x57@2x.png</string> <string>AppIcon60x60@2x.png</string> </array> </dict> </dict> <key>CFBundleIcons~ipad</key> <dict> <key>CFBundlePrimaryIcon</key> <dict> <key>CFBundleIconFiles</key> <array> <string>AppIcon29x29.png</string> <string>AppIcon29x29@2x.png</string> <string>AppIcon40x40@2x.png</string> <string>AppIcon57x57.png</string> <string>AppIcon57x57@2x.png</string> <string>AppIcon60x60@2x.png</string> <string>AppIcon29x29~ipad.png</string> <string>AppIcon29x29@2x~ipad.png</string> <string>AppIcon40x40~ipad.png</string> <string>AppIcon40x40@2x~ipad.png</string> <string>AppIcon50x50~ipad.png</string> <string>AppIcon50x50@2x~ipad.png</string> <string>AppIcon72x72~ipad.png</string> <string>AppIcon72x72@2x~ipad.png</string> <string>AppIcon76x76~ipad.png</string> <string>AppIcon76x76@2x~ipad.png</string> </array> </dict> </dict>
This ensures that the appropriate files are copied to the right place and the correct icons are used as required by the Apple App Store. Ad-hoc distributions should also include the following filenames in the application bundle to visualize the application in iTunes:
Every iOS app must provide a launch screen to be displayed while the app launches. A launch screen is an interface builder
.xib
file, also called a storyboard file. For more information, see
Specifying Your App's Launch Screen
.
Support for launch screens has been introduced in iOS 9.0.
Both qmake and CMake generate a default launch screen called
LaunchScreen.storyboard
.
To specify a custom launch screen, it must be copied to the application bundle, and the
UILaunchStoryboardName
key must be set to the name of the launch screen in the
Info.plist
文件。
Qt supports custom launch screens with CMake since Qt 6.4, and with qmake since Qt 6.0.
Assuming that the launch file is called
Launch.storyboard
, it can be added to
Info.plist
如下:
<key>UILaunchStoryboardName</key> <string>Launch</string>
To copy the launch screen into the application bundle with qmake, use the following code snippet in your project .pro file:
ios { QMAKE_IOS_LAUNCH_SCREEN = $$PWD/Launch.storyboard }
With CMake:
qt_add_executable(app) if(IOS) set_target_properties(app PROPERTIES QT_IOS_LAUNCH_SCREEN "${CMAKE_CURRENT_SOURCE_DIR}/Launch.storyboard") endif()
It's also possible to specify launch images (PNG files) instead of launch screen.
注意: Using launch images is not recommended, because support for them has been deprecated since iOS 13.0. Consider switching to launch screens instead.
Launch images must be copied to the application bundle and their names must be set in the
Info.plist
文件使用
UILaunchImages
key.
The following images must be prepared:
The images can be added to
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>
To copy the launch images into the application bundle with qmake, use the following code snippet in your project .pro file:
ios { app_launch_images.files = $$files($$PWD/ios/LaunchImage*.png) QMAKE_BUNDLE_DATA += app_launch_images }
With 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()
注意:
Earlier iOS versions supported specifying a single launch image using the
UILaunchImageFile
key in
Info.plist
, but support for it has been deprecated since iOS 10.0.
若
Info.plist
file contains an entry for
NSPhotoLibraryUsageDescription
, qmake will automatically include an extra plugin which enables access to the native image picker. If the directory in your
QFileDialog
is set to:
QStandardPaths::standardLocations(QStandardPaths::PicturesLocation).last();
or alternatively the folder in a FileDialog in QML to:
shortcuts.pictures
then the native image picker is shown to allow access to the user's photo album.
Apple platforms have a built-in way to express the OS versions that an application supports, which allows older versions of the platforms to automatically display a user friendly error message prompting the user to update their OS, as opposed to crashing and displaying a stack trace.
The main concepts involved in expressing support for a particular range of OS versions are:
When you develop an application for an Apple platform, you should always use the latest version of Xcode and the latest SDK available at the time of development. On some platforms, like iOS, you will actually be rejected from the App Store if you do not. Therefore, the SDK version is always greater than or equal to the deployment target.
When you develop an application for an Apple platform, you must set the deployment target. Various build tools within the Xcode toolchain all have a flag which you can use to set this value, including but not limited to the compiler and linker. By setting the deployment target value, you are explicitly declaring that your application must work on at least that version, and will not work with any earlier versions of the OS. It is then up to you to ensure that your use of the system APIs matches what you have declared. Since the compiler knows what you have declared, it can help in enforcing that.
The SDK version is considered a soft maximum version of the OS that an application is compatible with in the way that if the application is built with an SDK, it will continue to use the behaviors of that SDK even on newer OS versions, because the OS checks the binary's load commands and emulates backwards compatibility with the older OS. For example, if an application is built with the macOS 10.12 SDK, it will continue to use 10.12 behaviors even on 10.13 and above.
However, Mach-O binaries are inherently forward compatible. For example, an application built with the iOS 9 SDK will run just fine on iOS 10, but might not be opted into whatever behavior changes may have been made to certain functionality on the new release, until that application is recompiled against that newer SDK.
The minimum OS version can be expressed to the system by the compiler and linker flags that embed it into the Mach-O binary. In addition, the
LSMinimumSystemVersion
key must be set in the application's app bundle. This value must be equal to the value passed to the compiler and linker, because on macOS it will allow the OS to display a user friendly error dialog that says the application requires a newer version of the OS as opposed to a crash dialog. The
LSMinimumSystemVersion
is also the key that the App Store uses to display the required OS version; the compiler and linker flags have no power there.
For the most part, Qt applications will work without problems. For example, in qmake, the Qt mkspecs set
QMAKE_IOS_DEPLOYMENT_TARGET
or
QMAKE_MACOSX_DEPLOYMENT_TARGET
to the minimum version that Qt itself supports. Similarly, in Qbs, the Qt modules set
cpp.minimumIosVersion
,
cpp.minimumMacosVersion
,
cpp.minimumTvosVersion
,或
cpp.minimumWatchosVersion
to the minimum version that Qt itself supports.
However, you must take care when you manually set your own target version. If you set it to a value higher than what Qt requires and supply your own
Info.plist
file, you must add an
LSMinimumSystemVersion
entry to the
Info.plist
that matches the value of the deployment target, because the OS will use the
LSMinimumSystemVersion
value as the authoritative one.
If you specify a deployment target value lower than what Qt requires, the application will almost certainly crash somewhere in the Qt libraries when run on an older version than Qt supports. Therefore, make sure that the actual build system code reflects the minimum OS version that is actually required.
Verifying that your Qt for iOS application is ready for publishing to App Store can be done as described in Submitting the Application . To submit the application, you can use Xcode, or the Application Loader (installed with Xcode). Qt Creator does not provide an interface for managing all of the settings in an Xcode project configuration.
The application should be tested on the iOS versions and devices that it is targeted to support. The minimum deployment target for Qt applications varies by Qt version. For more information, see supported configurations .
The actual publishing process involves creating a distribution certificate and a provision profile, creating a signed archive of your application, and running a set of validation tests on it.
见 App Distribution Guide in iOS Developer Library for more information.
In the context of linking C++ libraries, functions and objects are referred to as symbols. Symbols can have either
default
or
hidden
visibility
.
For performance reasons, Qt and many other libraries compile their sources using
hidden
visibility by default, and only mark symbols with
default
visibility when they are meant to be used in user projects.
Unfortunately the Apple linker can issue warnings when one library is compiled with
hidden
visibility and a user project application or library is compiled with
default
visibility.
If project developers want to silence the warning, they need to build their project code with
hidden
visibility as well.
In CMake that can be done by adding the following code to the your
CMakeLists.txt
:
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
In qmake that can be done by adding the following code to your
.pro
文件:
CONFIG+=hide_symbols
In case if a project builds libraries, any symbols in the library that are meant to be used in another library or application will have to be explicitly marked with
default
visibility. For example, that can be done by annotating such functions or classes with
Q_DECL_EXPORT
.
Due to an issue in CMake , trying to create a product archive with an iOS application may fail.
This can happen both when trying to create the archive in Xcode using the Product -> Archive menu item, or from the command line using
xcodebuild -archivePath
.
The error message might reference undefined symbols or non-existent file paths.
To work around the issue, make sure to manually rebuild the project before trying to create an archive.