2014-09-22 15 views
5

La mia app è una funzionalità di riproduzione di video sia in modalità orizzontale che verticale.videos può essere anche su youtube tutto funzionava bene fino a iOS 7 ma ora i video di YouTube non funzionano in modalità orizzontale su iOS 8.Il video di YouTube non viene riprodotto in modalità orizzontale in iOS 8

il mio codice:

- (NSUInteger)application:(UIApplication *)applicationsupportedInterfaceOrientationsForWindow:(UIWindow *)window { 


    if ([[window.rootViewController presentedViewController] 
    isKindOfClass:[MPMoviePlayerViewController class]] || [[window.rootViewController presentedViewController] isKindOfClass:NSClassFromString(@"MPInlineVideoFullscreenViewController")])  { 

     return UIInterfaceOrientationMaskAllButUpsideDown; 
    } else { 

     if ([[window.rootViewController presentedViewController] 
     isKindOfClass:[UINavigationController class]]) { 

      // look for it inside UINavigationController 
      UINavigationController *nc = (UINavigationController *)[window.rootViewController presentedViewController]; 

      // is at the top? 
      if ([nc.topViewController isKindOfClass:[MPMoviePlayerViewController class]]) { 
      return UIInterfaceOrientationMaskAllButUpsideDown; 

      // or it's presented from the top? 
      } else if ([[nc.topViewController presentedViewController] 
        isKindOfClass:[MPMoviePlayerViewController class]]) { 
       return UIInterfaceOrientationMaskAllButUpsideDown; 
      } 
     } 
    } 

    return UIInterfaceOrientationMaskPortrait; 
} 

Tutto stava funzionando bene fino a iOS 7, ma smettere di lavorare su iOS 8. Qualsiasi aiuto apprezzato

risposta

14

bene il suo a volte stupido per rispondere alla tua domanda, ma va bene per aiutare gli altri che stanno affrontando lo stesso problema.

in iOS 8 anziché controllare MPInlineVideoFullscreenViewController, è necessario controllare AVFullScreenViewController. Quindi di seguito è il metodo completo per tutte le versioni iOS i.e iOS 8 e meno.

- (NSUInteger)application:(UIApplication *)applicationsupportedInterfaceOrientationsForWindow:(UIWindow *)window { 

    if ([[window.rootViewController presentedViewController] 
    isKindOfClass:[MPMoviePlayerViewController class]] || [[window.rootViewController presentedViewController] isKindOfClass:NSClassFromString(@"MPInlineVideoFullscreenViewController")] || [[window.rootViewController presentedViewController] isKindOfClass:NSClassFromString(@"AVFullScreenViewController")]) { 

     return UIInterfaceOrientationMaskAllButUpsideDown; 
    }else { 

     if ([[window.rootViewController presentedViewController] 
     isKindOfClass:[UINavigationController class]]) { 

      // look for it inside UINavigationController 
      UINavigationController *nc = (UINavigationController *)[window.rootViewController presentedViewController]; 

      // is at the top? 
      if ([nc.topViewController isKindOfClass:[MPMoviePlayerViewController class]]) { 
       return UIInterfaceOrientationMaskAllButUpsideDown; 

       // or it's presented from the top? 
      } else if ([[nc.topViewController presentedViewController] 
        isKindOfClass:[MPMoviePlayerViewController class]]) { 
       return UIInterfaceOrientationMaskAllButUpsideDown; 
      } 
     } 
    } 

    return UIInterfaceOrientationMaskPortrait; 
} 

Aggiornamento: Opere in iOS 9 e

+4

cuv upvoted rispondere alla propria domanda non è sciocco. i pali senza risposta sono stupidi. – overeasy

+0

Grazie per la risposta, ho problemi a farlo funzionare su iOS7: i dettagli sono troppo grandi per un commento, ho fatto una nuova domanda http://stackoverflow.com/questions/26443485/fullscreen-video-screen-is-not -mpmovieplayerviewcontroller-on-ios7-device – Boaz

+0

Grazie per questo! La rotazione funziona come previsto quando la vista video è attiva. Sto riscontrando un problema in cui, dopo aver toccato il pulsante Fine mentre l'app è in modalità orizzontale, l'app torna in modalità verticale, ma la barra di spostamento non viene ridimensionata correttamente. L'altezza della barra di navigazione è inferiore a quella che dovrebbe essere. –

0

non ho potuto rilevare la AVFullScreenViewController nella mia app su iOS 8 Golden Master, ma trovare AVPlayerView fa il trucco.

UIViewController + VideoAutorotate.h

#import <UIKit/UIKit.h> 

@interface UIViewController (VideoAutorotate) 

@end 

UIViewController + VideoAutorotate.m

#import "UIViewController+VideoAutorotate.h" 

BOOL testAnyViewRecursively(UIView *view, BOOL (^test)(UIView *view)) { 
    if (test(view)) { 
     return YES; 
    } else { 
     for (UIView *subview in view.subviews) { 
      if (testAnyViewRecursively(subview, test)) { 
       return YES; 
      } 
     } 
    } 
    return NO; 
} 

@implementation UIViewController (VideoAutorotate) 

-(BOOL)shouldAutorotate 
{ 
    if (UI_PAD) { 
     return YES; 
    } else { 
     // iOS 6: MPInlineVideoFullscreenViewController in iOS 6 doesn't seem to override this method to return YES. 
     if ([NSStringFromClass([self class]) isEqual:@"MPInlineVideoFullscreenViewController"]) { 
      return YES; 
     } 
     // iOS 8: 
     return testAnyViewRecursively(self.view, ^BOOL(UIView *view) { 
      return [NSStringFromClass([view class]) isEqual:@"AVPlayerView"]; 
     }); 
    } 
} 
+0

non è stato possibile rilevare AVFullScreenViewController perché si stanno introspettendo le visualizzazioni anziché i controller di visualizzazione. – overeasy

+0

Quando ho provato a trovare 'AVFullScreenViewController', uso le righe di' [self class] 'per iOS 6 nel mio codice. – hiroshi

+0

@Rajat Grazie per aver raccolto un po 'di ortografia e grammatica, ma intendo che GM è "Golden Master" non GSM (Global System for Mobile communications). – hiroshi

5

Ho codice simile nella mia app, che ha rotto anche in iOS 8.

Volevo solo pubblicare la mia versione di questa correzione nel caso in cui aiuti qualcuno.

La differenza principale è che sto solo controllando il controller più presentato in alto.

Penso che questo abbia più senso dei condizionali nidificati che cercano di capire che tipo di vc sta presentando un altro vc.

In ogni caso, ho questo nella mia app delegato, e sta funzionando in gran 8.

- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window { 
    id presentedViewController = [self topMostController]; 

    if ([self vcIsVideoPlayer:presentedViewController]) { 
     return UIInterfaceOrientationMaskAll; 
    } else { 
     return UIInterfaceOrientationMaskPortrait; 
    } 
} 

- (UIViewController*) topMostController { 
    UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController; 

    while (topController.presentedViewController) { 
     topController = topController.presentedViewController; 
    } 

    return topController; 
} 

- (BOOL) vcIsVideoPlayer:(UIViewController *)vc { 
    NSString *className = vc ? NSStringFromClass([vc class]) : nil; 
    return (
      [className isEqualToString:@"MPInlineVideoFullscreenViewController"] || 
      [className isEqualToString:@"MPMoviePlayerViewController"] || 
      [className isEqualToString:@"AVFullScreenViewController"] 
      ); 
} 
+1

Funziona perfettamente ma quando il video smette di suonare il controller della vista sottostante viene presentato in orizzontale! – entropid

+0

Funziona come un incantesimo. Grazie – devxoul

3

Aggiornamento: Una cosa da aggiungere se si nota la vostra barra di stato rottura dopo si torna al controller da un video orizzontale è impostare la barra di stato come non nascosta a false in viewWillLayoutSubviews.

override func viewWillLayoutSubviews() { 
    super.viewWillLayoutSubviews() 
    UIApplication.sharedApplication().setStatusBarHidden(false, withAnimation: .None) 
} 

Per quelli in Swift, alcune note aggiuntive. Questo metodo (application:supportedInterfaceOrientationsForWindow) dovrebbe essere nella classe AppDelegate o qualsiasi altra cosa impostata su @UIApplicationMain. Per poter accedere alla classe MPMoviePlayerViewController, è necessario ricordare a import MoviePlayer.

In secondo luogo, il valore UIInterfaceOrientationMask non è compatibile con la versione Swift del delegato di per sé, quindi è necessario accedere rawValue e trasformare il conseguente Uint in un Int. Ecco la soluzione Swift per chi è nel bisogno.

func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow) -> Int { 
    var orientation = UIInterfaceOrientationMask.Portrait 

    if let presentedController = window.rootViewController?.presentedViewController { 

     //check for the controllers 
     if presentedController is MPMoviePlayerViewController || 
      presentedController.isKindOfClass(NSClassFromString("AVFullScreenViewController").self) || 
      presentedController.isKindOfClass(NSClassFromString("MPInlineVideoFullscreenViewController").self) { 
      orientation = .AllButUpsideDown 
     } 
     //otherwise, we may be inside a Nav. 
     //safely get the nav controller otherwise ignore this block 
     else if let navController = presentedController as? UINavigationController { 

      if navController.topViewController is MPMoviePlayerViewController || 
       navController.topViewController.isKindOfClass(NSClassFromString("AVFullScreenViewController").self) || 
       navController.topViewController.isKindOfClass(NSClassFromString("MPInlineVideoFullscreenViewController").self) { 
       orientation = .AllButUpsideDown 
      } 
     } 


    } 

    return Int(orientation.rawValue) 
} 
1

Questa è una soluzione in Swift testato su iOS7 e iOS8. Devi aggiungere questo metodo alla tua classe AppDelegate.

AppDelegate.swift

func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> Int { 

    var topController = UIApplication.sharedApplication().keyWindow?.rootViewController 

    if (topController != nil) { 
     while ((topController!.presentedViewController) != nil) { 
      topController = topController!.presentedViewController; 
     } 

     if (topController != nil && (topController!.className == "AVFullScreenViewController" || topController!.className == "MPFullScreenTransitionViewController")) { 
      return Int(UIInterfaceOrientationMask.All.rawValue); 
     } 

    } 

    return Int(UIInterfaceOrientationMask.Portrait.rawValue); 
} 
+0

Ricevo questo errore: metodo Objective-C 'application: supportedInterfaceOrientationsForWindow:' fornito dal metodo 'application (_: supportedInterfaceOrientationsForWindow :)' è in conflitto con il metodo del requisito facoltativo 'application (_: supportedInterfaceOrientationsForWindow :)' nel protocollo 'UIApplicationDelegate' . C'è qualcos'altro che devi fare per implementare questo codice? – tomDev

0

Ecco Swift versione 3 per iOS 10.1. Ho modificato la risposta di Anthony Persaud qui. Per verificare if presentedController.isKind(of: MPMoviePlayerViewController.self), avrai bisogno di import MediaPlayer nella parte superiore.

func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask { 

    if let presentedController = window?.rootViewController?.presentedViewController, 
     let avFullScreen = NSClassFromString("AVFullScreenViewController").self, 
     let mpInlineVideoFullscreen = NSClassFromString("MPInlineVideoFullscreenViewController").self { 

     if presentedController.isKind(of: MPMoviePlayerViewController.self) || 
      presentedController.isKind(of: avFullScreen) || 
      presentedController.isKind(of: mpInlineVideoFullscreen) { 
      return UIInterfaceOrientationMask.allButUpsideDown 
     } 
    } 

    return UIInterfaceOrientationMask.portrait 

} 
Problemi correlati