2014-12-02 5 views
36

Ho un'applicazione iOS7, basata sul modello di dettaglio master Xcode, che sto eseguendo il porting su iOS8. Un'area che è cambiata molto è la UISplitViewController.Nascondere il controller della vista principale con UISplitViewController in iOS8

In modalità ritratto, se l'utente tocca sul controller vista di dettaglio, il controller della vista maestro è respinto:

enter image description here

Vorrei anche essere in grado di nascondere programmazione del controller della vista master se l'utente tocca una riga.

In iOS 7, il controllore vista principale veniva visualizzato come popover, e potrebbe essere nascosto come segue:

[self.masterPopoverController dismissPopoverAnimated:YES]; 

Con iOS 8, il master non è più un popover, per cui la tecnica di cui sopra non funzionerà.

Ho cercato di respingere il controller della vista maestro:

self.dismissViewControllerAnimated(true, completion: nil) 

o dire il controller vista divisa per visualizzare i dettagli View Controller:

self.splitViewController?.showDetailViewController(bookViewController!, sender: self) 

Ma niente ha funzionato finora. Qualche idea?

+0

potete per favore accettare una delle risposte qui sotto? – phatmann

risposta

54

Estendere l'UISplitViewController come segue:

extension UISplitViewController { 
    func toggleMasterView() { 
     let barButtonItem = self.displayModeButtonItem() 
     UIApplication.sharedApplication().sendAction(barButtonItem.action, to: barButtonItem.target, from: nil, forEvent: nil) 
    } 
} 

In didSelectRowAtIndexPath o prepareForSegue, effettuare le seguenti operazioni:

self.splitViewController?.toggleMasterView() 

Questo sarà senza intoppi far scorrere la vista principale fuori strada.

Mi è venuta l'idea di utilizzare il displayModeButtonItem() da this post e sto simulando un tap su di esso per this post.

Non sono davvero contento di questa soluzione, poiché sembra un trucco. Ma funziona bene e sembra che non ci sia ancora un'alternativa.

+0

Bella soluzione. Ho appena provato questo e funziona come previsto, animando il popover in modalità ritratto iPad. L'unico lieve effetto collaterale è che questo nasconde anche la vista principale quando in iPhone 6+ modalità Landscape (ma non su iPad) - un altro gioioso modo in cui l'iPhone 6+ non è né un telefono né un tablet! – pjh68

+1

Ho finito per implementare un bypass specifico del dispositivo per iPhone 6 Plus: vedere http://stackoverflow.com/questions/25780283/ios-how-to-detect-iphone-6-plus-iphone-6-iphone-5-by -macro per un modo semplice di rilevare questo. – pjh68

+1

Hey risposta molto bella, funziona, ma ho un altro problema. Animare anche il cambiamento del controller della vista di dettaglio. Sta succedendo anche a te? Grazie – Sanandrea

9

Utilizzare preferredDisplayMode. In didSelectRowAtIndexPath o prepareForSegue:

self.splitViewController?.preferredDisplayMode = .PrimaryHidden 
self.splitViewController?.preferredDisplayMode = .Automatic 

Purtroppo la vista maestro scompare bruscamente, invece di scivolare via, nonostante la documentazione attestante:

Se cambiare il valore di questa proprietà porta ad un effettivo cambiamento nella corrente modalità di visualizzazione, il controller della vista divisa anima la modifica risultante .

Speriamo che ci sia un modo migliore per fare ciò che effettivamente anima il cambiamento.

+0

Questo non funziona affatto. La vista principale rimane sullo schermo dopo che è stata selezionata una riga e non appare affiancata in modalità orizzontale. – phatmann

+0

@phatmann funziona, ho cercato di aggiungere questo codice nel mio didSelectRowAtIndexPath: - (void) tableView: (UITableView *) tableView didSelectRowAtIndexPath: (NSIndexPath *) indexPath { self.splitViewController.preferredDisplayMode = UISplitViewControllerDisplayModePrimaryHidden; } –

+1

Se inserisco il codice sopra in 'prepareForSegue', la vista principale scompare effettivamente. Ho anche dovuto chiamare 'preferredDisplayMode = .Automatic' subito dopo quindi l'operazione landscape è corretta. Il problema è che la vista principale non scivola via facilmente, rendendo questa tecnica meno che ideale. D'altra parte, nessuno ha ancora fornito una risposta migliore, quindi grazie! – phatmann

8

Sono stato in grado di ottenere il comportamento desiderato in un Xcode 6 .3 Master-Detail Application (universale) del progetto aggiungendo il seguente codice nel - prepareForSegue:sender: metodo s' il MasterViewController:

if view.traitCollection.userInterfaceIdiom == .Pad && splitViewController?.displayMode == .PrimaryOverlay { 
    let animations:() -> Void = { 
     self.splitViewController?.preferredDisplayMode = .PrimaryHidden 
    } 
    let completion: Bool -> Void = { _ in 
     self.splitViewController?.preferredDisplayMode = .Automatic 
    } 
    UIView.animateWithDuration(0.3, animations: animations, completion: completion) 
} 

La completa - prepareForSegue:sender: attuazione dovrebbe assomigliare a questo:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { 
    if segue.identifier == "showDetail" { 
     if let indexPath = self.tableView.indexPathForSelectedRow() { 
      let object = objects[indexPath.row] as! NSDate 
      let controller = (segue.destinationViewController as! UINavigationController).topViewController as! DetailViewController 
      controller.detailItem = object 
      controller.navigationItem.leftBarButtonItem = self.splitViewController?.displayModeButtonItem() 
      controller.navigationItem.leftItemsSupplementBackButton = true 

      if view.traitCollection.userInterfaceIdiom == .Pad && splitViewController?.displayMode == .PrimaryOverlay { 
       let animations:() -> Void = { 
        self.splitViewController?.preferredDisplayMode = .PrimaryHidden 
       } 
       let completion: Bool -> Void = { _ in 
        self.splitViewController?.preferredDisplayMode = .Automatic 
       } 
       UIView.animateWithDuration(0.3, animations: animations, completion: completion) 
      } 
     } 
    } 
} 

Utilizzando traitCollection può anche essere un'alternativa/supplemento a displayMode in alcuni progetti. Ad esempio, il seguente codice funziona anche per un Xcode 6.3 Master-Detail Application (universale) del progetto:

let traits = view.traitCollection 
if traits.userInterfaceIdiom == .Pad && traits.horizontalSizeClass == .Regular { 
    let animations:() -> Void = { 
     self.splitViewController?.preferredDisplayMode = .PrimaryHidden 
    } 
    let completion: Bool -> Void = { _ in 
     self.splitViewController?.preferredDisplayMode = .Automatic 
    } 
    UIView.animateWithDuration(0.3, animations: animations, completion: completion) 
} 
+0

Una soluzione superiore – AlexD

0

La mia soluzione nel Swift 1,2

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath){ 
    var screen = UIScreen.mainScreen().currentMode?.size.height 
    if (UIDevice.currentDevice().userInterfaceIdiom == UIUserInterfaceIdiom.Pad) || screen >= 2000 && UIDevice.currentDevice().orientation.isLandscape == true && (UIDevice.currentDevice().userInterfaceIdiom == .Phone){ 
     performSegueWithIdentifier("showDetailParse", sender: nil) 
     self.splitViewController?.preferredDisplayMode = UISplitViewControllerDisplayMode.PrimaryHidden 
    } else if (UIDevice.currentDevice().userInterfaceIdiom == .Phone) { 
     performSegueWithIdentifier("showParse", sender: nil) 
    } 
} 
6

Il codice sotto nasconde la vista maestro con animazione

UIView.animateWithDuration(0.5) {() -> Void in 
      self.splitViewController?.preferredDisplayMode = .PrimaryHidden 
     } 
+0

Semplice e funziona per iOS 10, Swift 3.0 –

+0

@jithinroy Funziona !!! Sono rimasto bloccato per giorni GRAZIE !!!! –

3

Solo migliorando un po 'le risposte elencate qui, il seguente codice funziona correttamente per me, e io t gestisce anche l'animazione senza intoppi:

extension UISplitViewController { 
    func toggleMasterView() { 
     var nextDisplayMode: UISplitViewControllerDisplayMode 
     switch(self.preferredDisplayMode){ 
     case .PrimaryHidden: 
      nextDisplayMode = .AllVisible 
     default: 
      nextDisplayMode = .PrimaryHidden 
     } 
     UIView.animateWithDuration(0.5) {() -> Void in 
      self.preferredDisplayMode = nextDisplayMode 
     } 
    } 
} 

e poi, come detto, è sufficiente utilizzare la funzione estesa ovunque nella vista controller

self.splitViewController?.toggleMasterView() 
0

per iPad pulsante Menu aggiungere come questo

UIBarButtonItem *menuButtonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"burger_menu"] 
                     style:UIBarButtonItemStylePlain 
                     target:self.splitViewController.displayModeButtonItem.target 
                     action:self.splitViewController.displayModeButtonItem.action]; 
[self.navigationItem setLeftBarButtonItem:menuButtonItem]; 

Questo funziona perfettamente con la modalità orizzontale e verticale. Per chiudere programmazione del vc popover è sufficiente forzare l'azione pulsante mi piace questo

[self.splitViewController.displayModeButtonItem.target performSelector:appDelegate.splitViewController.displayModeButtonItem.action]; 
1

Modifica le risposte di sopra di questo è tutto quello che serviva in un metodo di mio controller vista di dettaglio che configura la vista:

[self.splitViewController setPreferredDisplayMode:UISplitViewControllerDisplayModePrimaryHidden]; 

Naturalmente manca la grazia dell'animazione.

0

provare

let svc = self.splitViewController 
svc.preferredDisplayMode = UISplitViewControllerDisplayMode.PrimaryHidden