UISplitViewController: ¿Cómo obligar a mostrar el popover maestro en el inicio de la aplicación? (retrato)

En una aplicación de iPad, estoy usando UISplitViewController. Necesito forzar para mostrar el popover maestro cuando la aplicación se inicia en modo vertical.

Ahora estoy usando este código y funciona bien en iOS 5.0.

if (UIInterfaceOrientationIsPortrait(self.interfaceOrientation)) {
   if ([[[AppDelegate sharedAppDelegate] splitViewController] respondsToSelector:[[[AppDelegate sharedAppDelegate] btnMenu] action]]) {
      [[[AppDelegate sharedAppDelegate] splitViewController] performSelector:[[[AppDelegate sharedAppDelegate] btnMenu] action]];
   }            
}

Pero en iOS 5.1 (con el nuevo tipo de popover maestro) el comportamiento parece ser aleatorio. A veces, la ventana emergente se muestra en pantalla completa y, a veces, funciona bien.

¿Alguna sugerencia para 5.1?

preguntado el 03 de mayo de 12 a las 08:05

Aquí tienes una buena respuesta: stackoverflow.com/a/15817100/733862 -

8 Respuestas

No hay sugerencias aquí para 5.1, pero sí para 8.0:

Ahora con iOS8, hay un montón de nuevos métodos para UISplitViewController configuración.

En su caso, simplemente establezca el valor correcto en preferredDisplayMode, por ejemplo en el masterViewController viewDidLoad.

C objetivo:

- (void)viewDidLoad {
    // configuring splitviewcontroller
    self.splitViewController.preferredDisplayMode = UISplitViewControllerDisplayModeAllVisible;

    //....
}

Swift:

    override func viewDidLoad() {
        self.splitViewController?.preferredDisplayMode = UISplitViewControllerDisplayMode.AllVisible
    }

Pero, por supuesto, solo es iOS8.

Respondido 22 Abr '16, 12:04

Esto fuerza la visualización en paralelo. No muestra la vista maestra en modo popover como solicitó el OP. - phatmann

@phatmann, no creo que alejandromp estuviera hablando de popover. Él dice Necesito forzar para mostrar el maestro popover pero eso no significa nada, de hecho. Teniendo en cuenta el contexto, habla de mostrar la vista maestra una al lado de la otra en modo vertical, como en paisaje. - Martin

también se puede llamar en detailViewController - fujianjin6471

Luché con este por un tiempo, e incluso ahora no estoy 100% satisfecho con la solución, pero es lo único que he podido encontrar, dadas las limitaciones actuales.

Primero, invalide el siguiente método de delegado:

- (void)splitViewController:(UISplitViewController *)splitController willHideViewController:(UIViewController *)viewController withBarButtonItem:(UIBarButtonItem *)barButtonItem forPopoverController:(UIPopoverController *)popoverController

y utilícelo para obtener una referencia al elemento del botón de la barra y guárdelo en un iVar:

barButtonForMaster = barButtonItem;

Luego, cuando desee mostrar el controlador de vista maestro, haga una llamada como esta:

[barButtonForMaster.target performSelector: barButtonForMaster.action withObject: barButtonForMaster];

En caso de que desee realizar esto desde el principio, use un poco de retraso para evitar que la aplicación se bloquee (gracias al útil comentario):

[barButtonForMaster.target performSelector: barButtonForMaster.action withObject: barButtonForMaster afterDelay:1];

En ese caso, puede realizar el selector directamente en el método de delegado de vista dividida.

Respondido el 06 de enero de 14 a las 03:01

Gracias. Hago esto con su código más mi código anterior. Pero a veces la aplicación falla. Creo que es porque lo hago en el delegado splitViewController y tal vez, en algunos casos, el controlador no está completamente creado. Ahora hago ese código con perfromSelectorAfterDelay y funciona muy bien. Gracias. - alejandromp

Esto dará como resultado una posible advertencia de fuga de memoria del compilador: Anders

Ampliando la respuesta de Rob, esto funciona bien para mí (en viewDidLoad de la pantalla de detalles):

//If in portrait mode, display the master view
if (UIInterfaceOrientationIsPortrait(self.interfaceOrientation)) {
    [self.navigationItem.leftBarButtonItem.target performSelector:self.navigationItem.leftBarButtonItem.action withObject:self.navigationItem];
}

No es necesario buscar una referencia separada, usando self.navigationItem.leftBarButtonItem en su lugar

respondido 06 nov., 12:19

esto es increíble y funciona perfectamente! Sin embargo, me está dando una advertencia, "PerformSelector puede causar una fuga porque su selector es desconocido". ¿Sabría por qué y qué hacer al respecto? - BObereder

AFAIK, el compilador analiza las llamadas a métodos y agrega código para administrar los contadores de referencia ARC (para administrar la recolección de basura). Llamar a un método como este es como usar reflejos en Java (hecho durante el tiempo de ejecución), por lo que el compilador no puede hacer su magia refCount en este caso. Sin embargo, siempre que el método llamado no devuelva ningún objeto asignado (lo que sería una fuga), no habrá ningún problema. En este caso, no devolvemos nada del método llamado. Para evitar esta advertencia, consulte: aprendizajeipadprogramming.com/2012/04/03/… - Setomidor

Esto no funciona si no se carga nada en el controlador de vista detallada, que sería el punto principal para obligar a que se muestre el maestro. - Víctor Engel

@VictorEngel lo hace, pero dado que este código entra en la vista de detalles, debe asegurarse de cargar una vista de detalles vacía de forma predeterminada. - Setomidor

Para iOS8, la forma más fácil es con lo siguiente:

 self.splitViewController.preferredDisplayMode = UISplitViewControllerDisplayModePrimaryOverlay;

Lo uso cuando la aplicación se inicia por primera vez para mostrar el inicio de sesión en masterViewController. En todos los demás casos uso

self.splitViewController.preferredDisplayMode = UISplitViewControllerDisplayModeAutomatic

contestado el 29 de mayo de 15 a las 10:05

Si lo necesita al iniciar la aplicación, anule este método en su controlador de vista de detalles:

-(BOOL)splitViewController:(UISplitViewController *)svc shouldHideViewController:(UIViewController *)vc inOrientation:(UIInterfaceOrientation)orientation
{
    return NO;
}

Sin embargo, si luego necesita que se oculte posteriormente, parece que no se llama al método, por lo que tendrá que ocultarlo manualmente.

Respondido 14 Jul 14, 06:07

Esto está obsoleto en iOS 8. - phatmann

Una variación ligeramente menos hacky (swift):

let btn = self.splitViewController!.displayModeButtonItem()
btn.target?.performSelector(btn.action, withObject: btn)

Respondido 27 Feb 16, 17:02

Yo uso esta solución:
En splitViewController en viewDidLoad establezca displayMode en .primaryOverlay

override func viewDidLoad() {
    if self.isCollapsed == false, self.displayMode == .primaryHidden {
        self.preferredDisplayMode = .primaryOverlay
    }
}

Y en viewWillAppear configúralo de nuevo en .automatic

override func viewWillAppear(_ animated: Bool) {
    self.preferredDisplayMode = .automatic
}

De esta manera, la vista maestra se mostrará al iniciar UISplitViewController y tendrá un comportamiento predeterminado después de que cambie la orientación.

Respondido 15 Jul 17, 23:07

No es necesario mantener referencias tontas al barButtonItem. Simplemente llama al mismo objetivo/acción. ver mi respuesta https://stackoverflow.com/a/25695923/1021430

El objetivo es el controlador de vista dividida y la acción es toggleMasterVisible:

contestado el 23 de mayo de 17 a las 13:05

Ese toggleMasterVisible es un método privado. - Víctor Engel

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.