path: root/src/plugins/platforms/ios/
diff options
authorRichard Moe Gustavsen <>2015-11-06 12:47:13 +0100
committerRichard Moe Gustavsen <>2015-11-09 08:50:36 +0000
commitabf47610c716955b894e6ee20cc0dae00929799a (patch)
treeec65d0208c7d731f5939db49e632b57734622da6 /src/plugins/platforms/ios/
parentacb9db32b20344c74109ecbe5b4da493c9d7afc3 (diff)
iOS: only force-finish start-up from file engine when on main thread
The authorization dialog that grants the application access to the assets will only show after returning back from applicationDidFinishLaunching. Therefore, trying to load an asset from main before qApp->exec() would normally fail. To remedy that, we added a path that starts a QEventLoop for a split second to force the application init process to finish. But this can only work if we start it from the main thread. A bug with this is seen in QML FileDialog, since it (clumsy enough) starts to iterate, in a separate thread, all the files in its currently set directory upon start-up construction (which should be fixed as well). The result is that the application gets dead-locked on start-up. Change-Id: I0047272d53314752903960b33f88b33dc0d7e78d Reviewed-by: Tor Arne Vestbø <>
Diffstat (limited to 'src/plugins/platforms/ios/')
1 files changed, 26 insertions, 14 deletions
diff --git a/src/plugins/platforms/ios/ b/src/plugins/platforms/ios/
index 761a89c989..bb12c164d6 100644
--- a/src/plugins/platforms/ios/
+++ b/src/plugins/platforms/ios/
@@ -48,20 +48,29 @@ static QThreadStorage<QPointer<QIOSAssetData> > g_assetDataCache;
static const int kBufferSize = 10;
static ALAsset *kNoAsset = 0;
-static void ensureAuthorizationDialogNotBlocked()
+static bool ensureAuthorizationDialogNotBlocked()
if ([ALAssetsLibrary authorizationStatus] != ALAuthorizationStatusNotDetermined)
- return;
+ return true;
if (static_cast<QCoreApplicationPrivate *>(QObjectPrivate::get(qApp))->in_exec)
- return;
- // Since authorization status has not been determined, the user will be asked
- // to authorize the app. But since main has not finished, the dialog will be held
- // back until the launch completes. To avoid a dead-lock below, we start an event
- // loop to complete the launch.
- QEventLoop loop;
- QTimer::singleShot(1, &loop, &QEventLoop::quit);
- loop.exec();
+ return true;
+ if ([NSThread isMainThread]) {
+ // The dialog is about to show, but since main has not finished, the dialog will be held
+ // back until the launch completes. This is problematic since we cannot successfully return
+ // back to the caller before the asset is ready, which also includes showing the dialog. To
+ // work around this, we create an event loop to that will complete the launch (return from the
+ // applicationDidFinishLaunching callback). But this will only work if we're on the main thread.
+ QEventLoop loop;
+ QTimer::singleShot(1, &loop, &QEventLoop::quit);
+ loop.exec();
+ } else {
+ NSLog(@"QIOSFileEngine: unable to show assets authorization dialog from non-gui thread before QApplication is executing.");
+ return false;
+ }
+ return true;
// -------------------------------------------------------------------------
@@ -80,8 +89,10 @@ public:
, m_writeIndex(0)
, m_nextAssetReady(false)
- ensureAuthorizationDialogNotBlocked();
- startEnumerate();
+ if (!ensureAuthorizationDialogNotBlocked())
+ writeAsset(kNoAsset);
+ else
+ startEnumerate();
@@ -186,7 +197,8 @@ public:
, m_assetUrl(assetUrl)
, m_assetLibrary(0)
- ensureAuthorizationDialogNotBlocked();
+ if (!ensureAuthorizationDialogNotBlocked())
+ return;
if (QIOSAssetData *assetData = g_assetDataCache.localData()) {
// It's a common pattern that QFiles pointing to the same path are created and destroyed