Support for iOS and tvOS

From Qt Wiki
Jump to: navigation, search

Introduction

If this page is in a crude state, it's because it's a quick brain dump of experiences taking a simple (QQuickView + QML, minimal UI) app from Linux & macOS Desktop to iOS or tvOS, and written in the hope it will be useful to other developers with Qt/Desktop experience who are quite unfamiliar with "mobile" and iOS and tvOS and Xcode. Please feel free to edit mercilessly. This page doesn't (yet) describe App Store submissions.

Prerequisites

  • You'll need an iOS or tvOS device.
  • To deploy an application onto an iOS or tvOS device, you'll need a key (or "team provisioning profile" as Apple calls it) from Apple to sign the executables. The easiest way to get this is probably to register on the Apple Developer Program. An annual fee must be paid.
  • You need Xcode, and therefore a Mac running macOS.
  • You need the iOS or tvOS device connected to your Mac via the provided USB.
  • You need to "Provision Your Device for Development": this can be done from the Xcode device organizer: https://developer.apple.com/library/ios/recipes/xcode_help-devices_organizer/articles/provision_device_for_development-generic.html
  • You need a Qt x.x.x for iOS or tvOS SDK (note that this also includes the macOS support; whereas if you download the Qt x.x.x for macOS SDK, it's just the macOS stuff. Hence the considerably larger size of the iOS or tvOS SDK).

(If you're happy just programming Xcode's device simulators then you just need a Xcode and a Mac running macOS; there's no need to register as an Apple developer for that. Be warned the simulator performance characteristics are significantly different from real HW!)

Workflow (not using QtCreator)

Preparation

Assuming you have a Qt project which builds for desktop from a qmake .pro file, you should be able to get an iOS or tvOS build by:

  • Get the right tools in your path: You'll find the iOS or tvOS Qt SDK has both (e.g for Qt 5.10) 5.10/clang_64/bin/ and 5.10/ios/bin or 5.10/tvos/bin. The clang_64 one is for macOS; make sure it's the iOS or tvOS version of the tools is in your path for the below.
  • Run
    qmake -spec macx-xcode myproject.pro
    
    . You can add iOS specific .pro file details in an "ios { }" block, tvOS specific .pro file details in a "tvos { }" block, or details specific for both iOS and tvOS in a "uikit { }" block (note that uikit also includes watchOS).
    QMAKE_BUNDLE_DATA
    
    is probably the most useful, notably for adding the arcane set of application icons needed by various devices (note that Xcode asset catalogs can also help a lot in this area).
  • Open the resulting myproject.xcodeproj in Xcode.
  • When qmake runs it also creates an Info.plist file (XML) which contains a great many interesting settings. While these can be tweaked from within Xcode, this isn't recommended as the next qmake run will obliterate any changes. Instead, it is better to have a script make any needed changes which can be run after a qmake. (There may be some QMAKE_ macros which set certain plist properties too.)
  • If you rerun the qmake, it's a good idea to close the Xcode project.

Info.plist

Useful settings (can be got into the qmake-generated Info.plist using sed/regexps/xslt transforms… whatever works for you - but note the existence of PListBuddy mentioned below):

Adding

  <key>UIFileSharingEnabled</key>
  <string>YES</string>
in the
<dict>
section enables "file sharing" (more on this below).

Adding

  <key>UISupportedInterfaceOrientations</key>
  <array>
    <string>UIInterfaceOrientationLandscapeLeft</string>
    <string>UIInterfaceOrientationLandscapeRight</string>
  </array>

locks the application to landscape mode (useful if it's been designed on Desktop aspect ratio screens!).

Adding

  <key>UIStatusBarHidden</key>
    <true/>
  <key>UIViewControllerBasedStatusBarAppearance</key>
    <false/>

hides the status bar (recent iOS versions; maybe version dependent).

Additionally/alternatively Apple provides a useful utility /usr/libexec/PlistBuddy for modifying these files e.g

  /usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString 1.2.3" Info.plist

would set a version number (not to be confused with CFBundleVersion, which appears to be intended for use as a build number).

Deploying

  • You can compile from the commandline using
    xcodebuild -project myproject.xcodeproj -alltargets
    
    . However, you'll still need to open Xcode and the xcodeproj to deploy it to an iOS or tvOS device. But it's useful for commandline mavens who'd rather not open Xcode until they absolutely have to.
  • In Xcode, hit the big "arrow" icon top left of xcode to "Build and then run the current scheme". If all goes well (assuming no compile errors), you'll get (if your target isn't a simulator) a dialog "codesign wants to sign using key" (you can opt to always allow this) and it'll deploy to the device (physical or simulator) you have selected just to the right of that arrow icon. Your application should start up on the device in a short while.
  • Note that Xcode's default behaviour is to build and run in debug mode. You can change this frome the Product->Scheme dialog (which is also where commandline options and environment variables can be set).
  • If Xcode doesn't seem to be "seeing" your iOS or tvOS device, some combination/escalation of unplug/replug , restart Xcode, restart Mac generally fixes it.
  • Any logging to stdout/stderr from your app appears in a window in Xcode, which is handy.

Other considerations about the iOS and tvOS environments

Stuff you need to know:

Files on iOS and tvOS devices

  • iOS and tvOS apps run in a "sandbox" where they keep their data. They don't get to mess with other apps data. When the app is uninstalled, the entire sandbox contents is deleted. There are some important conventions to be aware of.
  • You can transfer files to and from a Mac (using iTunes) to that sandbox if the app has enabled "file sharing" (see above mention re Info.plist).
  • Such file transferring does seem to be individual files. You can't select a folder and have that and all its contained files and subfolders be transferred. Solutions probably involve "container files" like tar or zip… more on this here.

https support

  • Since version 5.5, Qt makes use of the platforms's SecureTransport framework to provide QSslSocket functionality. This includes:
    • C++: QNetworkAccessManager
    • QML: XMLHttpRequest
  • The iOS platform does not expose OpenSSL as a public library, but it's possible to build and link OpenSSL manually. See QTBUG-3689.

"Installers" for iOS and tvOS

The workflow described above refers to deploying an app to a USB-attached iOS or tvOS device. If you want to send an "installer" for an app to someone remote with an iOS or tvOS device (NB must be one which has somehow been inducted into your limited pool of development/test machines, for example by adding the device GUID in your Apple developer account and creating and downloading a new app signing certificate including the device):

  • In Xcode, there is a "Product" menu with "Archive" on it (NB need to have iOS or tvOS device selected as build target, not a simulator).
  • That creates an archive in the Organizer window's Archives tab.
  • Select the archive and hit the "Distribute" button.
  • This brings up a dialog where you get to select "Save for Enterprise or Ad Hoc Deployment" then "use iOS/tvOS Team Provisioning Profile", and then save a .ipa file (an "iPhone application archive file" apparently).
  • Send the ipa file to the intended user.
  • If they double-click the ipa file it should open iTunes' to install or update the app on the device (when iTune's "apply" is hit).

Plugins

Qt's own plugins for image format support and QtQuick/QML just work.

If you're using your own custom plugins: these will need to be of the static variety until such time as Qt adds support for shared libraries on iOS and tvOS (targeted for 5.9 or 5.10).

This is slightly non-trivial (at least for QQmlExtension plugins); see thread at https://forum.qt.io/topic/56878/qml-plugin-on-ios and linked https://bugreports.qt.io/browse/QTBUG-47827 and example code at https://bitbucket.org/timday/qt-example-plugin/overview

General

  • If you're used to developing for desktop platforms, you may find the ratio of "graphics power" (OpenGL GPU rendering power) to conventional CPU "compute power" somewhat skewed (towards graphics) compared to your previous experience! QtQuick's QSG's separate rendering thread probably really pays off here, helping a couple of feeble ARM cores keep the PowerVR GPU beast fed.