Support for iOS and tvOS: Difference between revisions

From Qt Wiki
Jump to navigation Jump to search
(Update HTTPS support section to reflect SecureTransport-based SSL backend)
No edit summary
 
(3 intermediate revisions by 2 users not shown)
Line 1: Line 1:
= Support for iOS =
[[Category:iOS]]
[[Category:tvOS]]
== Introduction ==
== 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 & OS X Desktop to iOS, 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 Xcode. Please feel free to edit mercilessly. This page doesn't (yet) describe App Store submissions.
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 ==
== Prerequisites ==


* You'll need an iOS device.
* You'll need an iOS or tvOS device.
* To deploy an application onto an iOS 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 [https://developer.apple.com/programs/ios/ Apple iOS Developer Program]. A yearly fee must be paid.
* 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 [https://developer.apple.com/programs/ Apple Developer Program]. An annual fee must be paid.
* You need Xcode, and therefore a Mac running OS X.
* You need Xcode, and therefore a Mac running macOS.
* You need the iOS device connected to your Mac via the provided USB.
* You need the iOS or tvOS device connected to your Mac via the provided USB.
* You need to "Provision Your iOS 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 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 SDK (note that this also includes the OS X support; whereas if you download the Qt x.x.x for Mac SDK, it's just the OS X stuff. Hence the considerably larger size of the iOS SDK).  
* 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 iOS device simulators then you just need a Xcode and a Mac running OS X; there's no need to register as an iOS developer for that. Be warned the simulator performance characteristics are significantly different from real HW!)
(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) ==
== Workflow (''not'' using QtCreator) ==
Line 19: Line 20:
=== Preparation ===
=== Preparation ===


Assuming you have a Qt project which builds for desktop from a qmake .pro file, you should be able to get an iOS build by:
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 Qt SDK has both (e.g for Qt 5.3.1) 5.3/clang_64/bin/ and 5.3/ios/bin . The clang_64 one is for OS X; make sure it's the iOS version of the tools is in your path for the below.
* 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 <code>qmake -spec macx-xcode myproject.pro</code> . You can add iOS specific .pro file details in an "ios { }" block. <code>QMAKE_BUNDLE_DATA</code> 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).
* Run <code>qmake -spec macx-xcode myproject.pro</code> . 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). <code>QMAKE_BUNDLE_DATA</code> 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.
* Open the resulting myproject.xcodeproj in Xcode.
* The first time you do this, you'll probably need to create a myproject.xcworkspace workspace file to contain the project (c.f Visual Studio's "solutions" which contain projects). But once you've done that you can forget about it.  (Actually, XCode 6+ seems to be happy to just open an xcodeproj without any xcworkspace entanglements).
* 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.)  
* 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.
* If you rerun the qmake, it's a good idea to close the Xcode project.


=== Info.plist ===
=== Info.plist ===
Line 65: Line 65:
=== Deploying ===
=== Deploying ===


* You can compile from the commandline using <code>xcodebuild -project myproject.xcodeproj -alltargets</code> . However, you'll still need to open Xcode and the xcodeproj to deploy it to an iOS device. But it's useful for commandline mavens who'd rather not open Xcode until they absolutely have to.
* You can compile from the commandline using <code>xcodebuild -project myproject.xcodeproj -alltargets</code> . 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.
* 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).
* 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 device, some combination/escalation of unplug/replug , restart Xcode, restart Mac generally fixes it.
* 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.
* Any logging to stdout/stderr from your app appears in a window in Xcode, which is handy.


== Other considerations about the iOS environment ==
== Other considerations about the iOS and tvOS environments ==


Stuff you need to know:
Stuff you need to know:


=== Files on iOS devices ===
=== Files on iOS and tvOS devices ===


* iOS 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 [https://developer.apple.com/library/ios/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemOverview/FileSystemOverview.html important conventions to be aware of].
* 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 [https://developer.apple.com/library/ios/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemOverview/FileSystemOverview.html 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).
* 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 [http://forum.qt.io/viewthread/41012/#174257 here].
* 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 [http://forum.qt.io/viewthread/41012/#174257 here].
Line 88: Line 88:
* The iOS platform does not expose OpenSSL as a public library, but it's possible to build and link OpenSSL manually. See QTBUG-3689.
* 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 ===
=== "Installers" for iOS and tvOS ===


The workflow described above refers to deploying an app to a USB-attached iOS device.
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 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):
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 device selected as build target, not a simulator).
* 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.
* That creates an archive in the Organizer window's Archives tab.
* Select the archive and hit the "Distribute" button.
* 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 Team Provisioning Profile", and then save a .ipa file (an "iOS application archive file" apparently).
* 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.
* 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).
* 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).
Line 104: Line 104:
Qt's own plugins for image format support and QtQuick/QML just work.
Qt's own plugins for image format support and QtQuick/QML just work.


If you're using your own custom plugins: it's believed these will need to be of the static variety due to iOS restrictions on .dylib usage.
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).
Apple may have changed policy on this from iOS8+, although the new policy may be more about dylib use by reusable frameworks and it's not clear if application plugins are intended to be allowed too or not. In any case, CONFIG += plugin targets just seem to build static libs automatically on iOS even without CONFIG += static.


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
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

Latest revision as of 20:00, 16 February 2017

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.