2012-05-03 10 views
25

In un'app per iPad sto utilizzando UISplitViewController. Ho bisogno di forzare per mostrare il popover principale quando l'app si avvia in modalità verticale.UISplitViewController: come forzare la visualizzazione del popover principale nel lancio dell'app? (ritratto)

Ora sto usando questo codice e funziona bene su iOS 5.0.

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

Ma in iOS 5.1 (con il nuovo tipo di popover principale) il comportamento sembra essere casuale. A volte il popover mostra a schermo intero e talvolta funziona bene.

Alcuni suggerimenti per 5.1?

+1

Ecco una buona risposta: http://stackoverflow.com/a/15817100/733862 – akofink

risposta

13

Ho lottato con questo per un po ', e anche ora non sono felice al 100% con la soluzione, ma è l'unica cosa che sono riuscito a trovare, visti gli attuali limiti.

In primo luogo, ignorare il seguente metodo delegato:

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

e utilizzarlo per afferrare un riferimento alla voce pulsante della barra, e conservarla in un iVar:

barButtonForMaster = barButtonItem; 

Poi, quando si vuoi mostrare il controller della vista master, effettuare una chiamata in questo modo:

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

Nel caso in cui si desidera formare questo fin dall'inizio, quindi utilizzare un certo ritardo per evitare che app crash (grazie al commento utile):

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

in tal caso è possibile eseguire il selettore proprio nel metodo delegato vista divisa.

+1

Grazie. Lo faccio con il tuo codice più il mio codice precedente. Ma a volte l'App si blocca. Penso che sia perché lo faccio nel delegato splitViewController e forse, in alcuni casi, il controller non è completamente creato. Ora faccio quel codice con perfromSelectorAfterDelay e lavoro molto bene. Grazie. – alejandromp

+0

Ciò comporterà in un compilatore l'avviso di perdita di memoria possibile – anders

13

Estendendosi su risposta di Rob, questa funziona bene per me (in viewDidLoad dello schermo particolare):

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

Non c'è bisogno di prendere un riferimento separato, utilizzando self.navigationItem.leftBarButtonItem invece

+0

questo è sorprendente e funziona perfettamente! mi sta dando un avvertimento però, "PerformSelector potrebbe causare una perdita perché il suo selettore è sconosciuto" sapresti perché e cosa fare al riguardo? – bllubbor

+2

AFAIK il compilatore analizza le chiamate di metodo e aggiunge il codice per gestire i contatori di riferimento ARC (per gestire la Garbage Collection). Chiamare un metodo come questo è un po 'come usare le riflessioni in Java (fatto durante il runtime), quindi il compilatore non può fare la magia refCount in questo caso. Tuttavia, finché il metodo chiamato non restituisce alcun oggetto allocato (che quindi sarebbe una perdita), non ci saranno problemi. In questo caso, non restituiremo nulla dal metodo chiamato. Per evitare questo avviso, vedere: http://www.learningipadprogramming.com/2012/04/03/how-to-ignore-performselector-leak-warning/ – Setomidor

+1

sorprendente grazie. – bllubbor

5

Se bisogno al momento del lancio di app, ignorare questo metodo nel controller vista di dettaglio:

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

Tuttavia, se è quindi necessario per nascondere in seguito sembra che il il metodo non viene chiamato, quindi dovrai nasconderlo manualmente.

+0

Grazie! Questa dovrebbe essere la risposta accettata. – Bill

+1

Questo è obsoleto in iOS 8. – phatmann

0

Non c'è bisogno di mantenere riferimenti stupidi intorno al barButtonItem. Basta chiamare lo stesso obiettivo/azione. Vedere la mia risposta https://stackoverflow.com/a/25695923/1021430

La destinazione è il controller della vista divisa, e l'azione è toggleMasterVisible:

+0

Questo toggleMasterVisible è un metodo privato. –

26

Nessun suggerimento qui per 5.1, ma uno per 8.0:

Ora con iOS 8, ci sono un sacco di nuovi metodi per la configurazione di UISplitViewController.

Nel proprio caso, è necessario impostare il valore corretto in preferredDisplayMode, ad esempio nel masterViewController viewDidLoad.

Objective-C:

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

    //.... 
} 

Swift:

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

Ma è ovviamente solo iOS 8.

+5

Questo forza il display side-by-side. Non mostra la vista principale in modalità popover come l'OP richiesto. – phatmann

+0

@phatmann, non penso che alejandromp stesse parlando di popover. Dice * Ho bisogno di forzare per mostrare il padrone popover * ma questo non significa niente, in effetti. Considerando il contesto, parla di visualizzazione della vista principale affiancata in modalità verticale, come in orizzontale. – Martin

+0

può anche essere chiamato in dettaglioViewController – fujianjin6471

7

Per iOS 8 il modo più semplice è la seguente:

self.splitViewController.preferredDisplayMode = UISplitViewControllerDisplayModePrimaryOverlay; 

io uso questo quando l'applicazione viene avviata per la prima volta per mostrare log-in in masterViewController. In tutti gli altri casi che uso

self.splitViewController.preferredDisplayMode = UISplitViewControllerDisplayModeAutomatic 
1

Una variante leggermente meno hacky (veloce):

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

utilizzo questa soluzione:
In splitViewController in viewDidLoad impostato displayMode a .primaryOverlay

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

E in viewWillAppear è impostato su .automatic

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

In questo modo verrà visualizzata la vista principale all'avvio di UISplitViewController e il comportamento predefinito dopo l'orientamento cambierà.

Problemi correlati