Comment utiliser un UISplitViewController en tant que controller modal View?

J'essaie d'afficher un UISplitViewController en le présentant comme un controller Modal View dans mon application iPad. Je parviens à l'afficher, mais pour une raison quelconque, il y a un espace à gauche de la vue modale, la taille d'une barre d'état qui est également conservée lorsque l'orientation est modifiée.

texte alt

Est-ce que quelqu'un sait pourquoi cela se passe? Ou si c'est même possible? Peut-être que je me suis creusé un énorme trou.

Le stock UISplitViewController été conçu pour être utilisé uniquement comme controller de vue racine. Présenter une modalité va à l'encontre des lignes direcsortingces d'Apple sur les interfaces humaines et a de fortes chances d'être rejetée par l'équipe d'examen des applications. En outre, vous pouvez recevoir l'erreur:

L'application a essayé de présenter les controllers Split View de manière modale

Comme pour beaucoup d'entre vous, j'avais besoin d'un 'mode modal' pour utiliser UISplitViewController. Cela semble être un vieux problème, mais tout ce que j'ai trouvé dans StackOverflow était au mieux une explication de la raison pour laquelle le problème se produit lorsque vous essayez de le faire (comme la réponse acceptée ci-dessus), ou «piratage».

Cependant, il n'est parfois pas très pratique de changer une grande partie de votre base de code et de faire d'UISplitViewController l'object initial juste pour que ses fonctionnalités soient opérationnelles.

En fin de count, il y a un moyen de rendre tout le monde heureux (y compris les lignes direcsortingces d'Apple). La solution que j'ai trouvée la meilleure, était d'utiliser le UISplitViewController normalement, mais quand nécessaire pour être montré / rejeté, utilisez l'approche suivante:

 -(void)presentWithMasterViewController: (UIViewController *) thisMasterViewController andDetailViewController: (UIViewController *) thisDetailViewController completion:(void(^)(void))completion { masterViewController = thisMasterViewController; detailViewController = thisDetailViewController; [self setViewControllers:[NSArray arrayWithObjects:masterViewController, detailViewController, nil]]; self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; self.window.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight; self.window.rootViewController = self; [self.window makeKeyAndVisible]; if(completion) completion(); } -(void)dismissViewControllerWithCompletion:(void (^)(void))completion { self.window = nil; masterViewController = nil; detailViewController = nil; if(completion) completion(); } 

Où "window", est une propriété de votre sous-class UISplitViewController. Et le système s'occupera du rest!

Par commodité / reference, j'ai téléchargé ceci sous forme de sous-class UISplitViewController à gitHub:

ModalSplitViewController

–EXEMPLE SUR L'UTILISATION –

  mySplitViewController = [[ModalSplitViewController alloc] init]; mySplitViewController.delegate = self; [mySplitViewController presentWithMasterViewController:masterViewController andDetailViewController:detailViewController completion:nil]; // when done: [mySplitViewController dismissViewControllerWithCompletion:nil]; mySplitViewController = nil; 

Side-note: Je suppose que la plupart de la confusion provient du fait que l'exemple d'utilisation UISplitView de la documentation Apple utilise la window créée dans appDelegate, et pour le fait que la plupart des gens ne sont pas si familiers avec le concept de window. pas besoin de (ils sont créés une fois dans StoryBoards ou un code standard).

De plus, si vous effectuez une restauration d'état, il ne faut pas oublier que les UIViewControllers créés par programme ne seront pas automatiquement restaurés par le système.

Techniquement, c'est ce que j'ai fait:

1 / Sous-class a UIViewController ie. @interface aVC: UIViewController

2 / Dans viewDidLoad, configurez un splitViewController, c.-à-d. aSplitVC

3 / Alors self.view = aSplitVC.view

Après tout, présenter aVC comme modalViewController

Je suis d'accord avec Evan sur le fait que c'est légèrement décalé pour Apple, mais j'ai été capable de compléter une version de travail avec la solution suivante:

 UISplitViewController *splitVC = [[UISplitViewController alloc] init]; splitVC.delegate = VC2; splitVC.viewControllers = [NSArray arrayWithObjects:navcon1, navcon2, nil]; UINavigationController *splitNavCon = [[UINavigationController alloc] init]; splitNavCon.modalTransitionStyle = UIModalTransitionStyleCoverVertical; [splitNavCon.view addSubview:splitVC.view]; VC2.splitParentViewController = splitNavCon; [self presentViewController:splitNavCon animated:YES completion:nil]; 

Cela m'a permis d'avoir un button de return dans le nouveau UISplitViewController qui a été présenté de façon modale sur l'écran.

Vous remarquerez que je passe réellement le VC2 (le délégué de l'UISplitViewController) à son parent UINavigationController. C'était le meilleur moyen que j'ai trouvé que je pouvais rejeter le UISplitViewController depuis le VC2:

 [splitParentViewController dismissViewControllerAnimated:YES completion:nil]; 

Je crois que l'on peut faire l'inverse: au lieu d'un controller personnalisé présentant un controller partagé, on peut configurer le controller séparé en tant que controller de window racine dans le storyboard, et en plus on peut append votre controller personnalisé (c.-à-d. ) et supprimez-le de l'écran (removeFromSuperview par exemple) quand il est nécessaire.

Cette réponse n'est pas vraiment correcte, car elle n'est plus valide depuis iOS8 et si vous avez besoin de supporter même iOS7, vous pouvez le faire comme vous l'avez fait avec UIViewController qui a un conteneur comme SplitView.

 let mdSplitView = self.storyboard?.instantiateViewControllerWithIdentifier("myDataSplitView") as! MyData_SplitVC self.addChildViewController(mdSplitView) mdSplitView.view.bounds = self.view.bounds self.view.addSubview(mdSplitView.view) mdSplitView.didMoveToParentViewController(self)