iOS: use an explicit pointer to qiosViewController

As it stood, we always relied on the root view controller
being a QIOSViewController if isQtApplication() returned
true. For mixed application, this might not always be true
as native code can choose to replace the root view controller
at times, or even rip it out, and place it as a child of
another (e.g UISplitViewController).
This change will give an extra protection against that.

Change-Id: I0cb85796a8b82f9037c32f9e85e04e1dc7aad8e2
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@digia.com>
This commit is contained in:
Richard Moe Gustavsen 2013-04-15 15:15:36 +02:00 committed by The Qt Project
parent 963b8dabef
commit 5ea3845bd0
7 changed files with 17 additions and 7 deletions

View File

@ -42,9 +42,12 @@
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>
#import <QtGui/QtGui> #import <QtGui/QtGui>
#import "qiosviewcontroller.h"
@interface QIOSApplicationDelegate : UIResponder <UIApplicationDelegate> @interface QIOSApplicationDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window; @property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) QIOSViewController *qiosViewController;
@end @end

View File

@ -46,6 +46,7 @@
@implementation QIOSApplicationDelegate @implementation QIOSApplicationDelegate
@synthesize window; @synthesize window;
@synthesize qiosViewController;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{ {
@ -85,6 +86,7 @@
- (void)dealloc - (void)dealloc
{ {
[qiosViewController release];
[window release]; [window release];
[super dealloc]; [super dealloc];
} }

View File

@ -52,7 +52,7 @@ QT_BEGIN_NAMESPACE
class QPlatformScreen; class QPlatformScreen;
bool isQtApplication(); bool isQtApplication();
QIOSViewController *rootViewController(); QIOSViewController *qiosViewController();
CGRect toCGRect(const QRect &rect); CGRect toCGRect(const QRect &rect);
QRect fromCGRect(const CGRect &rect); QRect fromCGRect(const CGRect &rect);

View File

@ -58,10 +58,14 @@ bool isQtApplication()
return isQt; return isQt;
} }
QIOSViewController *rootViewController() QIOSViewController *qiosViewController()
{ {
// If Qt controls the application, we have created a root view controller were we place top-level
// QWindows. Note that in a mixed native application, our view controller might later be removed or
// added as a child of another controller. To protect against that, we keep an explicit pointer to the
// view controller in cases where this is the controller we need to access.
static QIOSViewController *c = isQtApplication() ? static QIOSViewController *c = isQtApplication() ?
static_cast<QIOSViewController *>([UIApplication sharedApplication].delegate.window.rootViewController) : nil; static_cast<QIOSApplicationDelegate *>([UIApplication sharedApplication].delegate).qiosViewController : nil;
return c; return c;
} }

View File

@ -142,7 +142,7 @@ QIOSScreen::QIOSScreen(unsigned int screenIndex)
if (isQtApplication()) { if (isQtApplication()) {
// When in a non-mixed environment, let QScreen follow the current interface orientation: // When in a non-mixed environment, let QScreen follow the current interface orientation:
setPrimaryOrientation(toQtScreenOrientation(UIDeviceOrientation(rootViewController().interfaceOrientation))); setPrimaryOrientation(toQtScreenOrientation(UIDeviceOrientation(qiosViewController().interfaceOrientation)));
} }
[pool release]; [pool release];

View File

@ -375,7 +375,7 @@ void QIOSWindow::setVisible(bool visible)
requestActivateWindow(); requestActivateWindow();
} else { } else {
// Activate top-most visible QWindow: // Activate top-most visible QWindow:
NSArray *subviews = rootViewController().view.subviews; NSArray *subviews = qiosViewController().view.subviews;
for (int i = int(subviews.count) - 1; i >= 0; --i) { for (int i = int(subviews.count) - 1; i >= 0; --i) {
UIView *view = [subviews objectAtIndex:i]; UIView *view = [subviews objectAtIndex:i];
if (!view.hidden) { if (!view.hidden) {
@ -431,7 +431,7 @@ void QIOSWindow::setParent(const QPlatformWindow *parentWindow)
UIView *parentView = reinterpret_cast<UIView *>(parentWindow->winId()); UIView *parentView = reinterpret_cast<UIView *>(parentWindow->winId());
[parentView addSubview:m_view]; [parentView addSubview:m_view];
} else if (isQtApplication()) { } else if (isQtApplication()) {
[rootViewController().view addSubview:m_view]; [qiosViewController().view addSubview:m_view];
} }
} }

View File

@ -56,7 +56,8 @@ extern int qt_main(int argc, char *argv[]);
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{ {
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease]; self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
self.window.rootViewController = [[[QIOSViewController alloc] init] autorelease]; self.qiosViewController = [[[QIOSViewController alloc] init] autorelease];
self.window.rootViewController = self.qiosViewController;
#ifdef QT_DEBUG #ifdef QT_DEBUG
self.window.backgroundColor = [UIColor cyanColor]; self.window.backgroundColor = [UIColor cyanColor];