BR: iPad Pro 12.9 - iOS 17.2 - rotation no longer working

Hi @reuk I’ve actually implemented a minor change (see below) to the JUCE codebase, which puts the UIScheme implementation under JUCE control, which is I guess where we’d all like it :slight_smile:

My motivation for doing the work below, was just in case that resolved my issue - but it didn’t. That means that I’m pretty certain that the issue in question, somehow, is in my own code. I just can’t figure it out. It is just a real stinker - but that is my problem!

Note: app initialisation is moved to UISceneDelegate:willConnectToSession:connectionOptions

On a side note, when the app rotates, this is called:

- (void)windowScene:(UIWindowScene *_Nonnull)windowScene didUpdateCoordinateSpace:(id<UICoordinateSpace>_Nonnull)previousCoordinateSpace interfaceOrientation:(UIInterfaceOrientation)previousInterfaceOrientation traitCollection:(UITraitCollection *_Nonnull)previousTraitCollection

Add to the top of juce_Windowing_ios.mm …:

@interface MyUIScene : UIWindowScene
@end

@implementation MyUIScene
- (instancetype)initWithSession:(UISceneSession *)session connectionOptions:(UISceneConnectionOptions *)connectionOptions {
  self = [super initWithSession:session connectionOptions:connectionOptions];
  if (self) {
  }
  return self;
}
@end

@interface MyUISceneDelegate : NSObject<UIWindowSceneDelegate>
@end

@implementation MyUISceneDelegate

- (instancetype)init {
  self = [super init];
  if (self) {
  }
  return self;
}

// UISceneDelegate

- (void)scene:(UIScene *_Nonnull)scene willConnectToSession:(UISceneSession *_Nonnull)session options:(UISceneConnectionOptions *_Nonnull)connectionOptions {

  if (JUCEApplicationBase::getInstance() == nullptr) {
    if (auto* app = JUCEApplicationBase::createInstance())
    {
      if (! app->initialiseApp())
        exit (app->shutdownApp());
    }
    else
    {
      jassertfalse; // you must supply an application object for an iOS app!
    }
  }
}

- (void)sceneDidDisconnect:(UIScene *_Nonnull)scene {
}


- (void)sceneDidBecomeActive:(UIScene *_Nonnull)scene {
}

- (void)sceneWillResignActive:(UIScene *_Nonnull)scene {
}


- (void)sceneWillEnterForeground:(UIScene *_Nonnull)scene {
}

- (void)sceneDidEnterBackground:(UIScene *_Nonnull)scene {
}

- (void)scene:(UIScene *_Nonnull)scene openURLContexts:(NSSet<UIOpenURLContext *> *_Nonnull)URLContexts {
}

- (nullable NSUserActivity *)stateRestorationActivityForScene:(UIScene *_Nonnull)scene {
  return nil;
}

- (void)scene:(UIScene *_Nonnull)scene restoreInteractionStateWithUserActivity:(NSUserActivity *_Nonnull)stateRestorationActivity {
}

- (void)scene:(UIScene *_Nonnull)scene willContinueUserActivityWithType:(NSString *_Nonnull)userActivityType {
}

- (void)scene:(UIScene *_Nonnull)scene continueUserActivity:(NSUserActivity *_Nonnull)userActivity {
}

- (void)scene:(UIScene *_Nonnull)scene didFailToContinueUserActivityWithType:(NSString *_Nonnull)userActivityType error:(NSError *_Nonnull)error {
}

- (void)scene:(UIScene *_Nonnull)scene didUpdateUserActivity:(NSUserActivity *_Nonnull)userActivity {
}

// UIWindowSceneDelegate

- (void)windowScene:(UIWindowScene *_Nonnull)windowScene didUpdateCoordinateSpace:(id<UICoordinateSpace>_Nonnull)previousCoordinateSpace interfaceOrientation:(UIInterfaceOrientation)previousInterfaceOrientation traitCollection:(UITraitCollection *_Nonnull)previousTraitCollection {

}

- (void)windowScene:(UIWindowScene *_Nonnull)windowScene performActionForShortcutItem:(UIApplicationShortcutItem *_Nonnull)shortcutItem completionHandler:(void(^_Nonnull)(BOOL succeeded))completionHandler {

}

- (void)windowScene:(UIWindowScene *_Nonnull)windowScene userDidAcceptCloudKitShareWithMetadata:(CKShareMetadata *_Nonnull)cloudKitShareMetadata {

}

@end

// Replace this:

- (void) applicationDidFinishLaunching: (UIApplication*) application
{
    ignoreUnused (application);
    initialiseJuce_GUI();

//    if (auto* app = JUCEApplicationBase::createInstance())
//    {
//        if (! app->initialiseApp())
//            exit (app->shutdownApp());
//    }
//    else
//    {
//        jassertfalse; // you must supply an application object for an iOS app!
//    }
}

// Add this (which initialises the UIScene)

- (UISceneConfiguration *)application:(UIApplication *)application
configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options {

  UISceneConfiguration* result = [[UISceneConfiguration alloc] initWithName:@"MyUIScene" sessionRole:UIWindowSceneSessionRoleApplication];

  result.sceneClass = MyUIScene.class;
  result.delegateClass = MyUISceneDelegate.class;
  return result;
}

In juce_UIViewComponentPeer_ios.mm
In UIViewComponentPeer::UIViewComponentPeer method…
Replace code as shown:

    if (isSharedWindow)
    {
        window = [viewToAttachTo window];
        [viewToAttachTo addSubview: view];
    }
    else
    {
      r = convertToCGRect (component.getBounds());
      r.origin.y = [UIScreen mainScreen].bounds.size.height - (r.origin.y + r.size.height);

      // window = [[JuceUIWindow alloc] initWithFrame: r];
      // [((JuceUIWindow*) window) setOwner: this];

      // Create window so that it is owned by the scene (scene should already be available)
      bool bFoundScene = false;
      UIApplication* sharedApplication = [UIApplication sharedApplication];
      if (sharedApplication != nil) {
        for (UIScene* scene in [sharedApplication connectedScenes]) {
          if ([scene isKindOfClass: [UIWindowScene class]]) {
            UIWindowScene* uiWindowScene = (UIWindowScene*)scene;
            bFoundScene = true;
            window = [[JuceUIWindow alloc] initWithWindowScene:uiWindowScene];
            break;
          }
        }
      }

      if (bFoundScene == false) {
        // Unexpected!
        window = [[JuceUIWindow alloc] initWithFrame: r];
      }

      [((JuceUIWindow*) window) setOwner: this];

      controller = [[JuceUIViewController alloc] init];