İOS 8'de görünüm denetleyicisi yönünü zorlama


149

İOS 8'den önce, aşağıdaki yönlendirmeyi desteklenenInterfaceOrientations ile birlikte kullandık ve uygulama yönlendirmesini belirli bir yöne zorlamak için mustAutoRotate delege yöntemlerini kullandık. Aşağıdaki kod snippet'ini programlı olarak uygulamayı istenen yöne döndürmek için kullandım. İlk olarak, durum çubuğu yönünü değiştiriyorum. Ve sonra sadece bir modsal görünüm sunmak ve hemen kapatmak, görünümü istenen yöne döndürür.

[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight animated:YES];
UIViewController *c = [[UIViewController alloc]init];
[self presentViewController:vc animated:NO completion:nil];
[self dismissViewControllerAnimated:NO completion:nil];

Ancak bu iOS 8'de başarısız oluyor. Ayrıca, yığın taşmasında bazı insanların, iOS 8'den itibaren bu yaklaşımdan her zaman kaçınmamız gerektiğini önerdiği bazı cevaplar gördüm.

Daha açık olmak gerekirse, uygulamam evrensel bir uygulama türüdür. Toplamda üç kontrolör vardır.

  1. İlk Görünüm denetleyicisi - iPad'deki tüm yönleri ve iPhone'daki yalnızca dikey (ana sayfa düğmesi) desteklemelidir.

  2. İkinci Görünüm kontrolörü - Her koşulda yalnızca manzarayı desteklemelidir

  3. Üçüncü Görünüm denetleyicisi - Her koşulda yalnızca manzarayı desteklemelidir

Sayfada gezinmek için gezinti denetleyicisini kullanıyoruz. İlk görünüm denetleyicisinden, bir düğme tıklatma eyleminde, ikincisini yığın üzerinde itiyoruz. Bu nedenle, ikinci görünüm denetleyicisi geldiğinde, aygıt yönüne bakılmaksızın, uygulama yalnızca yatay olarak kilitlenmelidir.

Aşağıda benim shouldAutorotateve supportedInterfaceOrientationsikinci ve üçüncü görünüm denetleyicisindeki yöntemler verilmiştir.

-(NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskLandscapeRight;
}

-(BOOL)shouldAutorotate {
    return NO;
}

Bu veya iOS 8 için belirli bir yönde bir görünüm denetleyicisini kilitlemenin daha iyi bir yolu var mı? Lütfen yardım edin!


Sunulan VC'de bahsettiğiniz yöntemleri uygulamak genellikle işe yaramalıdır (en azından iOS 8'deki deneyimim). Belki de kendi kurulumunuz sorunlara neden oluyor?
Vladimir Gritsenko

Belki soruyu biraz daha açıklığa kavuşturabilirim. Soruyu biraz değiştireceğim.
Rashmi Ranjan mallick

@VladimirGritsenko: Lütfen şimdi kontrol edin. Ben düzenledim.
Rashmi Ranjan mallick

Sorudaki kod, navigasyon denetleyicisinin yığınını değil, modsal sunuyu kullanıyor, bu yüzden tam olarak ne yaptığınızı hala net değil. Kodumuzda, YES'i shouldAutoRotate'den döndürerek ve sunulan VC'deki desteklenenInterfaceOrientation'lardan istenen yönleri döndürmenin VC'yi doğru şekilde yönlendirdiğini söyleyeceğim .
Vladimir Gritsenko

Bu gerçekten bir başarısızlık değil, sadece konseptte büyük bir değişiklik. İyi bir değişim olup olmadığı tamamen başka bir konudur.
Kegluneq

Yanıtlar:


315

İOS 7-10 için:

Objective-C:

[[UIDevice currentDevice] setValue:@(UIInterfaceOrientationLandscapeLeft) forKey:@"orientation"];
[UINavigationController attemptRotationToDeviceOrientation];

Hızlı 3:

let value = UIInterfaceOrientation.landscapeLeft.rawValue
UIDevice.current.setValue(value, forKey: "orientation")
UINavigationController.attemptRotationToDeviceOrientation()

Sadece ara - viewDidAppear:Sunulan görünüm denetleyicisini yeterlidir.


61
Bu özel bir API değil . Bu, API'lerin güvenli olmayan şekilde kullanılmasıdır. Herhangi bir özel yöntem kullanmıyorsunuz, 'içsel şeyler' kullanıyorsunuz. Apple "yönlendirme" değerini değiştirirse başarısız olur. Daha da kötüsü: Apple "yön" değerinin anlamını değiştirirse, değeri sabit olarak neyi değiştirdiğinizi bilmiyorsunuzdur.
sonxurxo

4
Koymak devre dışı animasyon, To [UIView setAnimationsEnabled:NO];içinde viewWillAppearve [UIView setAnimationsEnabled:YES];içinde viewDidAppear: related, stackoverflow.com/a/6292506/88597
ohho

3
Güzel bir hack, ama bununla ilgili sorun, yeni yönlendirme değerini (iç çekme) ayarladıktan sonra didRotateFromInterfaceOrientation'u ateşlememesi
loretoparisi

2
İOS 9.2'de, bu yalnızca yön değiştiriyor, ancak kilitlenmiyor.
Mark13426

2
Bunu yapan herkesin zamanın% 90'ı iyi davrandığı ve zamanın diğer% 10'unun arabası olduğu için, yön tuşunu ayarladıktan sonra bunu çağırın:[UINavigationController attemptRotationToDeviceOrientation];
Albert Renshaw

93

A UINavigationControllerveya içindeyseniz yön rotasyonu biraz daha karmaşıktır UITabBarController. Sorun, bir denetleyicinin bu denetleyicilerden birine katıştırılmış olması durumunda, gezinme veya sekme çubuğu denetleyicisinin önceliğe sahip olması ve otomatik döndürme ve desteklenen yönler hakkında kararlar almasıdır.

UINavigationController ve UITabBarController üzerinde aşağıdaki 2 uzantıları kullanın, böylece bu denetleyicilerden birine katıştırılmış görünüm denetleyicileri kararlar alabilir.

Görünüm Denetleyicilerine Güç Ver!

Hızlı 2.3

extension UINavigationController {
    public override func supportedInterfaceOrientations() -> Int {
        return visibleViewController.supportedInterfaceOrientations()
    }
    public override func shouldAutorotate() -> Bool {
        return visibleViewController.shouldAutorotate()
    }
}

extension UITabBarController {
    public override func supportedInterfaceOrientations() -> Int {
        if let selected = selectedViewController {
            return selected.supportedInterfaceOrientations()
        }
        return super.supportedInterfaceOrientations()
    }
    public override func shouldAutorotate() -> Bool {
        if let selected = selectedViewController {
            return selected.shouldAutorotate()
        }
        return super.shouldAutorotate()
    }
}

Hızlı 3

extension UINavigationController {
    open override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        return visibleViewController?.supportedInterfaceOrientations ?? super.supportedInterfaceOrientations
    }

    open override var shouldAutorotate: Bool {
        return visibleViewController?.shouldAutorotate ?? super.shouldAutorotate
    }
}

extension UITabBarController {
    open override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        if let selected = selectedViewController {
            return selected.supportedInterfaceOrientations
        }
        return super.supportedInterfaceOrientations
    }

    open override var shouldAutorotate: Bool {
        if let selected = selectedViewController {
            return selected.shouldAutorotate
        }
        return super.shouldAutorotate
    }
}

Şimdi supportedInterfaceOrientationsyöntemi geçersiz kılabilir veya geçersiz kılabilirsinizshouldAutoRotate kilitlemek istediğiniz görünüm denetleyicisinde , aksi takdirde uygulamanızın plistinde belirtilen varsayılan yönlendirme davranışını devralmak istediğiniz diğer görünüm denetleyicilerinde geçersiz kılmaları kaldırabilirsiniz

Döndürmeyi Devre Dışı Bırak

class ViewController: UIViewController {
    override func shouldAutorotate() -> Bool {
        return false
    }
}

Belirli Yönlere Kilitle

class ViewController: UIViewController {
    override func supportedInterfaceOrientations() -> Int {
        return Int(UIInterfaceOrientationMask.Landscape.rawValue)
    }
}

Teoride bu, tüm karmaşık görünüm denetleyicisi hiyerarşileri için çalışmalıdır, ancak UITabBarController ile ilgili bir sorun fark ettim. Bazı nedenlerden dolayı varsayılan bir yönlendirme değeri kullanmak istiyor. Bazı sorunların nasıl çözüleceğini öğrenmek istiyorsanız aşağıdaki blog yayınına bakın:

Kilit Ekranı Döndürme


1
Bu çok eski bir yazı olduğunu biliyorum ama uzatma kodunu nereye koyardınız?
dwinnbrown

7
Bir Swift için aşağı işaretleme yalnızca bir Objective-C sorusuna cevap verir.
Charlie Scott-Skinner

17
Bu Swift ve ObjC için güzel bir çözüm. İnsanların neden oy kullanmadıklarını anlamıyorum. Fikriniz var ve kod yazmak kolay. Neden şikayet etmeliyim?
Zhao

2
@Krodak, Uzantılarda "-> Int" değerini "-> UIInterfaceOrientationMask" olarak değiştirmeyi deneyin. Benim için hile yaptı.
the_pantless_coder

2
Fikir ve kod mükemmel, ben onu seviyorum, ama UINavigationController kullanırken bir sorun var ve bir UIViewController manzara içinde görüntülenen bir dikey olarak görüntülenmesi gerekir. Herhangi bir fikir?
crisisGriega

24

Benim için işe yarayan buydu:

https://developer.apple.com/library//ios/documentation/UIKit/Reference/UIViewController_Class/index.html#//apple_ref/occ/clm/UIViewController/attemptRotationToDeviceOrientation

GörünümünüzDidAppear: yönteminde çağırın.

- (void) viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];

    [UIViewController attemptRotationToDeviceOrientation];
}

3
Cihaz zaten döndürülmüşse ve görünüm denetleyicinizi döndürmeniz gerekiyorsa çok kullanışlı
avdyushin

2
Mükemmel cevap. Kabul edilen cevapla birlikte kullanıldığında, bu benim Swift ve iOS 9+ 'da her zaman iyi çalışıyor.
AndyDunn

1
Her ne kadar sorulan sorunun cevabı olmadığını düşünüyorum, ama gerçekten bana yardımcı oldu.
Abdurrahman Mubeen Ali

21

Sunulan bir görünüm denetleyicisi ise, geçersiz kılabileceğinizi buldum preferredInterfaceOrientationForPresentation

Swift:

override func supportedInterfaceOrientations() -> Int {
  return Int(UIInterfaceOrientationMask.Landscape.rawValue)
}

override func preferredInterfaceOrientationForPresentation() -> UIInterfaceOrientation {
  return UIInterfaceOrientation.LandscapeLeft
}

override func shouldAutorotate() -> Bool {
  return false
}

4
Kabul edilen cevap basitçe manzaraya yönelme değişikliğini tetikliyor gibi görünüyor. Burada gösterdiğiniz şey, bir görünüm denetleyicisini yalnızca manzarada olmaya zorlamak ve sunan görünüm denetleyicisini etkilememektir (tam olarak ihtiyacım olan şeydir). Teşekkürler.
Clifton Labrum

1
@CliftonLabrum sadece manzarayı zorlamak için başka bir şey yaptınız mı ? Aynı kodu kullanarak, görünüm denetleyicisi yine de başka bir yöne dönebilir.
Crashalot

Daha sonra farkettim - haklısın. Henüz bir düzeltme bulamadım.
Clifton Labrum

1
Bu benim için çalıştı. Bu kodu (Landscape yerine Portrait ile değiştirerek) kullanarak tek bir View Controller'ı Portrait modunda tutabildim. +1
Mark Barrasso

Evet! Bu benim için Xcode 7.3 ve Swift 2.2'de de çalıştı. Ancak yine de AppDelegate'te desteklenenInterfaceOrientationsForWindow için func uygulamasını tanımlamanız gerekir.
charles.cc.hsu

16

Bu şekilde Swift 2 iOS 8.x'te benim için çalışıyor :

PS (bu yöntemin her viewController'da shouldautorotate gibi yönlendirme işlevlerini geçersiz kılması gerekmez, AppDelegate'te yalnızca bir yöntem vardır)

Proje genel bilgilerinizdeki "tam ekran gerektirir" seçeneğini işaretleyin. resim açıklamasını buraya girin

AppDelegate.swift üzerinde bir değişken yapın:

var enableAllOrientation = false

Öyleyse, bu işlevi de koyun:

func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> UIInterfaceOrientationMask {
        if (enableAllOrientation == true){
            return UIInterfaceOrientationMask.All
        }
        return UIInterfaceOrientationMask.Portrait
}

Böylece, projenizdeki her sınıfta bu değişkeni viewWillAppear'da ayarlayabilirsiniz:

override func viewWillAppear(animated: Bool)
{
        super.viewWillAppear(animated)
        let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
        appDelegate.enableAllOrientation = true
}

Cihaz türüne göre bir seçim yapmanız gerekirse bunu yapabilirsiniz:

override func viewWillAppear(animated: Bool)
    {
        super.viewWillAppear(animated)
        let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
        switch UIDevice.currentDevice().userInterfaceIdiom {
        case .Phone:
        // It's an iPhone
           print(" - Only portrait mode to iPhone")
           appDelegate.enableAllOrientation = false
        case .Pad:
        // It's an iPad
           print(" - All orientation mode enabled on iPad")
           appDelegate.enableAllOrientation = true
        case .Unspecified:
        // Uh, oh! What could it be?
           appDelegate.enableAllOrientation = false
        }
    }

çok güzel bir açıklama
Mihir Oza

11

Her şeyden önce - bu kötü bir fikirdir, genel olarak, uygulama mimarinizle ilgili yanlış bir şeydir, ancak sh..t happensöyleyse, aşağıdaki gibi bir şey yapmaya çalışabilirsiniz:

final class OrientationController {

    static private (set) var allowedOrientation:UIInterfaceOrientationMask = [.all]

    // MARK: - Public

    class func lockOrientation(_ orientationIdiom: UIInterfaceOrientationMask) {
        OrientationController.allowedOrientation = [orientationIdiom]
    }

    class func forceLockOrientation(_ orientation: UIInterfaceOrientation) {
        var mask:UIInterfaceOrientationMask = []
        switch orientation {
            case .unknown:
                mask = [.all]
            case .portrait:
                mask = [.portrait]
            case .portraitUpsideDown:
                mask = [.portraitUpsideDown]
            case .landscapeLeft:
                mask = [.landscapeLeft]
            case .landscapeRight:
                mask = [.landscapeRight]
        }

        OrientationController.lockOrientation(mask)

        UIDevice.current.setValue(orientation.rawValue, forKey: "orientation")
    }
}

Olduğundan AppDelegate

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    // do stuff
    OrientationController.lockOrientation(.portrait)
    return true
}

// MARK: - Orientation

func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
    return OrientationController.allowedOrientation
}

Yönü değiştirmek istediğinizde şu şekilde yapın:

OrientationController.forceLockOrientation(.landscapeRight)

Not: Bazen cihaz bu çağrıdan güncellenmeyebilir, bu nedenle aşağıdaki gibi yapmanız gerekebilir

OrientationController.forceLockOrientation(.portrait)
OrientationController.forceLockOrientation(.landscapeRight)

Bu kadar


9

Bu, iOS 6'dan yukarı doğru çalışmalıdır, ancak yalnızca iOS 8'de test ettim. Alt sınıfı UINavigationControllerve aşağıdaki yöntemleri geçersiz kılın:

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
    return UIInterfaceOrientationLandscapeRight;
}

- (BOOL)shouldAutorotate {
    return NO;
}

Veya görünür görünüm denetleyicisine sorun

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
    return self.visibleViewController.preferredInterfaceOrientationForPresentation;
}

- (BOOL)shouldAutorotate {
    return self.visibleViewController.shouldAutorotate;
}

ve yöntemleri oraya uygulamak.


Bu uygulamayı iOS 10.0 çalıştıran Xcode 8.2.1'de uyguladım ve işe yarıyor. Oyun menüm ilk ekran ve bu dönmüyor; diğer tüm görünümler döner. Mükemmel! Bir tane ver. Sadece Mojo66 tarafından verilen 'preferInterfaceOrientationForPresentation' işlevine ihtiyacım vardı.
Philip Borges

9

Bu, Sid Shah'ın cevabındaki , animasyonları kullanarak nasıl devre dışı bırakılacağıyla ilgili yorumlara bir geri bildirimdir :

[UIView setAnimationsEnabled:enabled];

Kod:

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:NO];
    [UIView setAnimationsEnabled:NO];

    // Stackoverflow #26357162 to force orientation
    NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeRight];
    [[UIDevice currentDevice] setValue:value forKey:@"orientation"];
}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:NO];
    [UIView setAnimationsEnabled:YES];
}

Bunu Portrait için nasıl kullanabilirim.
Muju

6

NavigationViewController kullanıyorsanız, bunun için kendi üst sınıfınızı oluşturmalı ve geçersiz kılmalısınız:

- (BOOL)shouldAutorotate {
  id currentViewController = self.topViewController;

  if ([currentViewController isKindOfClass:[SecondViewController class]])
    return NO;

  return YES;
}

bu, SecondViewController'da döndürmeyi devre dışı bırakır, ancak cihazınız dikey yönde olduğunda SecondViewController cihazınızı iterseniz , SecondViewController dikey modda görünür.

Film şeridi kullandığınızı varsayın. Manuel sekme ( Nasıl Yapılır ) ve "onClick" yönteminizde oluşturmanız gerekir:

- (IBAction)onPlayButtonClicked:(UIBarButtonItem *)sender {
  NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft];
  [[UIDevice currentDevice] setValue:value forKey:@"orientation"];
  [self performSegueWithIdentifier:@"PushPlayerViewController" sender:self];
}

Bu, üst sınıfınız otomatik döndürme özelliğini devre dışı bırakmadan önce yatay yönlendirmeyi zorlar.


6

Açık Xcode 8yöntemler özelliklerine dönüştürülür, aşağıdaki eserleri böylece Swift:

override public var supportedInterfaceOrientations: UIInterfaceOrientationMask {
    return UIInterfaceOrientationMask.portrait
}

override public var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
    return UIInterfaceOrientation.portrait
}

override public var shouldAutorotate: Bool {
    return true
}

Bu yönü kilitler mi?
bnussey

1
@bnussey portraitiPad'de yönelim ne olursa olsun otomatik dönüşü ve her zaman açık olmayı önlemek istedim , shouldAutorotatebunu doğru şekilde gerçekleştirdim.
Ali Momen Sani

4

Birçok çözüm denedim, ama işe yarayan şu:

info.plistİos 8 ve 9'da düzenleme yapmaya gerek yoktur .

- (BOOL) shouldAutorotate {
    return NO;
}   

- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
    return (UIInterfaceOrientationPortrait | UIInterfaceOrientationPortraitUpsideDown);
}

Apple Belgeleri'nden olası yönlendirmeler :

UIInterfaceOrientationUnknown

Cihazın yönü belirlenemiyor.

UIInterfaceOrientationPortrait

Cihaz dikey konumda ve cihaz dik ve altta ana sayfa düğmesi var.

UIInterfaceOrientationPortraitUpsideDown

Cihaz dikey modda ancak baş aşağı, cihaz dik ve üstteki ev düğmesi üstte.

UIInterfaceOrientationLandscapeLeft

Cihaz yatay konumda, cihaz dik tutulurken sol taraftaki ana sayfa düğmesi.

UIInterfaceOrientationLandscapeRight

Cihaz yatay konumda, cihaz dik tutulmuş ve ev düğmesi sağ tarafta.


3

Sids ve Koreys cevaplarının kombinasyonu benim için çalıştı.

Gezinti Denetleyicisini Genişletme:

extension UINavigationController {
    public override func shouldAutorotate() -> Bool {
        return visibleViewController.shouldAutorotate()
    }
}

Ardından tek Görünümde döndürmeyi devre dışı bırakma

class ViewController: UIViewController {
    override func shouldAutorotate() -> Bool {
        return false
    }
}

Ve segue öncesi uygun yöne dönme

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if (segue.identifier == "SomeSegue")
    {
        let value = UIInterfaceOrientation.Portrait.rawValue;
        UIDevice.currentDevice().setValue(value, forKey: "orientation")
    }
}

Bunun, görüntülenen görünüm denetleyicisinin her zaman olması gerektiği gibi dikey olarak dönmeden önce bir saniyeliğine manzarada olduğu sorunuma yardımcı olup olamayacağını biliyor musunuz? soru burada: stackoverflow.com/questions/30693964/…
dwinnbrown

3

Yukarıdaki en iyi çözüm:

let value = UIInterfaceOrientation.LandscapeLeft.rawValue
UIDevice.currentDevice().setValue(value, forKey: "orientation")

Sunulan görünüm denetleyicisinin viewDidAppear'da aradığımda benim için çalışmadı. Ancak ben sunan görünüm denetleyicisinde preparForSegue çağrıldığında işe yaradı.

(Üzgünüm, bu çözüm hakkında yorum yapmak için yeterli itibar puanı yok, bu yüzden böyle eklemek zorunda kaldım)


Bu çalışma var ama bir manzara görünümü denetleyicisinden bir portre görünümü denetleyicisine giderken, dikey olarak göstermesi gereken görünüm denetleyicisi kendi kendine dönmeden önce kısaca manzarada gösterilir. kimse nasıl yardımcı olabilirim sorum burada: stackoverflow.com/questions/30693964/…
dwinnbrown

viewDid'de @ dwinnbrown Görünüm denetleyicisi zaten görünür. Bunun yerine viewDidLoad'dan deneyebilirsiniz?
Crashalot

@Crashalot Şimdi bunu düzelttim. Lütfen doğru olarak işaretlediğim yanıta bakın.
dwinnbrown

@ dwinnbrown sorunuzun bağlantısı öldü. Güncelleme? Teşekkürler!
Crashalot

@Crashalot topluluğu sildi ancak silmeyi geri almak için oy verdim. Yakında size bildireceğim
dwinnbrown

3

[iOS9 +] Yukarıdaki çözümlerin hiçbiri işe yaramadığı için buraya kadar sürüklenen biri varsa ve yönünü segue ile değiştirmek istediğiniz görünümü sunarsanız, bunu kontrol etmek isteyebilirsiniz.

Segue'inizin sunum türünü kontrol edin. Benimki 'mevcut bağlamın üzerindeydi'. Tam ekran olarak değiştirdiğimde işe yaradı.

@GabLeRoux sayesinde, bu çözümü buldum.

  • Bu değişiklikler yalnızca yukarıdaki çözümlerle birleştirildiğinde işe yarar.

2

Gereksinimlerim

  1. dikey modda tüm görünümleri kilitleme
  2. kullanmak AVPlayerViewControllervideo oynatmak için

Video oynatılırken, bir manzara ise ekranın yatay ve sağa sola dönmesine izin verin. Portre ise, görünümü yalnızca portre modunda kilitleyin.

İlk olarak, tanımlar supportedInterfaceOrientationsForWindowiçindeAppDelegate.swift

var portrait = true
func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> UIInterfaceOrientationMask {
    if portrait {
        return .Portrait
    } else {
        return .Landscape
    }
}

İkinci olarak, ana görünüm denetleyicinizde aşağıdaki işlevleri tanımlayın

override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
    print("\(#function)")
    return .Portrait
}

override func preferredInterfaceOrientationForPresentation() -> UIInterfaceOrientation {
    return .Portrait
}

override func shouldAutorotate() -> Bool {
    return false
}

Sonra, alt sınıfa ihtiyacınız var AVPlayerViewController

class MyPlayerViewController: AVPlayerViewController {

    var size: CGSize?

    var supportedOrientationMask: UIInterfaceOrientationMask?
    var preferredOrientation: UIInterfaceOrientation?

    override func viewDidLoad() {
        super.viewDidLoad()

        if let size = size {
            if size.width > size.height {
                self.supportedOrientationMask =[.LandscapeLeft,.LandscapeRight]
                self.preferredOrientation =.LandscapeRight
            } else {
                self.supportedOrientationMask =.Portrait
                self.preferredOrientation =.Portrait
            }
        }
    }

Bu üç işlevi geçersiz kıl MyPlayerViewController.swift

override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
    return self.supportedOrientationMask!
}

override func preferredInterfaceOrientationForPresentation() -> UIInterfaceOrientation {
    return self.preferredOrientation!
}

Kullanıcı cihaz manzarasını sola veya yatay sağa döndürebileceğinden, otomatik döndürmeyi doğru olarak ayarlamamız gerekir

override func shouldAutorotate() -> Bool {
    return true
}

Son olarak, MyPlayerViewControllergörünüm denetleyicinizde örnek oluşturun ve özellik boyutu değerini ayarlayın.

let playerViewController = MyPlayerViewController()

// Get the thumbnail  
let thumbnail = MyAlbumFileManager.sharedManager().getThumbnailFromMyVideoMedia(......)

let size = thumbnail?.size
playerViewController.size = size

Oynatıcınızı uygun şekilde başlatın videoUrl, ardından oynatıcınızı atayın playerViewController. Mutlu kodlama!


2
- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    [UIViewController attemptRotationToDeviceOrientation];
}

1

Hala bu görevi en iyi şekilde nasıl yerine getirebileceğim konusunda bazı tartışmalar var gibi görünüyor, bu yüzden (çalışma) yaklaşımımı paylaşacağımı düşündüm. UIViewControllerUygulamanıza aşağıdaki kodu ekleyin :

- (void) viewWillAppear:(BOOL)animated
{
    [UIViewController attemptRotationToDeviceOrientation];
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
    return (toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft);
}

-(BOOL)shouldAutorotate
{
    return NO;
}

- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskLandscapeLeft;
}

Bu örnek için, proje ayarlarınızda (veya doğrudan içeri) izin verilen cihaz yönlerinizi 'Yatay Sola' ayarlamanız da gerekecektir info.plist. Başka bir şey istiyorsanız, zorlamak istediğiniz yönü değiştirinLandscapeLeft.

Benim için anahtar, attemptRotationToDeviceOrientationçağrı viewWillAppear- fiziksel olarak cihazı döndürmeden düzgün bir şekilde dönmeyecekti.


Onaylanmayan yöntem.
Saqib Omer

1

Göre Korey Hinton cevabı

Hızlı 2.2:

extension UINavigationController {
    public override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
        return visibleViewController!.supportedInterfaceOrientations()
    }
    public override func shouldAutorotate() -> Bool {
        return visibleViewController!.shouldAutorotate()
    }
}


extension UITabBarController {
    public override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
        if let selected = selectedViewController {
            return selected.supportedInterfaceOrientations()
        }
        return super.supportedInterfaceOrientations()
    }
    public override func shouldAutorotate() -> Bool {
        if let selected = selectedViewController {
            return selected.shouldAutorotate()
        }
        return super.shouldAutorotate()
    }
}

Döndürmeyi Devre Dışı Bırak

override func shouldAutorotate() -> Bool {
    return false
}

Belirli Yönlere Kilitle

override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
    return UIInterfaceOrientationMask.Portrait
}

1

Burada birkaç çözüm denedim ve anlamak için önemli olan şey, dönüp dönmeyeceğini belirleyecek olan kök görünüm denetleyicisidir.

Aşağıdaki objektif c projesi github.com/GabLeRoux/RotationLockInTabbedViewChild bir çalışma örneği ile oluşturdumTabbedViewController çocuk görünümünün dönmesine izin verildiği ve diğer çocuk görünümünün dikey olarak kilitlendiği .

Mükemmel değil ama işe yarıyor ve aynı fikir gibi kök görünümler için de çalışmalı NavigationViewController. :)

Alt görünüm üst yönlendirmeyi kilitler


0

@ Sid-sha tarafından gösterilen çözüme göre, her şeyi viewDidAppear:yönteme koymak zorundasınız , aksi takdirde didRotateFromInterfaceOrientation:kovulmayacaksınız, bu yüzden şöyle bir şey:

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    UIInterfaceOrientation interfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation];
    if (interfaceOrientation == UIInterfaceOrientationLandscapeLeft ||
        interfaceOrientation == UIInterfaceOrientationLandscapeRight) {
        NSNumber *value = [NSNumber numberWithInt:interfaceOrientation];
        [[UIDevice currentDevice] setValue:value forKey:@"orientation"];
    }
}

0

Çözümüm

İçinde AppDelegate:

func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> UIInterfaceOrientationMask {
    if let topController = UIViewController.topMostViewController() {
        if topController is XXViewController {
            return [.Portrait, .LandscapeLeft]
        }
    }
    return [.Portrait]
}

XXViewController Yatay modunu desteklemek istediğiniz ViewController.

Sonra Sunny Shah'ın çözümüXXViewController herhangi bir iOS sürümünde çalışacaktır :

let value = UIInterfaceOrientation.LandscapeLeft.rawValue
UIDevice.currentDevice().setValue(value, forKey: "orientation")

Bu, en üstteki ViewController'ı bulmak için yardımcı program işlevidir.

extension UIViewController {

    /// Returns the current application's top most view controller.
    public class func topMostViewController() -> UIViewController? {
        let rootViewController = UIApplication.sharedApplication().windows.first?.rootViewController
        return self.topMostViewControllerOfViewController(rootViewController)
    }



    /// Returns the top most view controller from given view controller's stack.
    class func topMostViewControllerOfViewController(viewController: UIViewController?) -> UIViewController? {
        // UITabBarController
        if let tabBarController = viewController as? UITabBarController,
           let selectedViewController = tabBarController.selectedViewController {
            return self.topMostViewControllerOfViewController(selectedViewController)
        }

        // UINavigationController
        if let navigationController = viewController as? UINavigationController,
           let visibleViewController = navigationController.visibleViewController {
            return self.topMostViewControllerOfViewController(visibleViewController)
        }

        // presented view controller
        if let presentedViewController = viewController?.presentedViewController {
            return self.topMostViewControllerOfViewController(presentedViewController)
        }

        // child view controller
        for subview in viewController?.view?.subviews ?? [] {
            if let childViewController = subview.nextResponder() as? UIViewController {
                return self.topMostViewControllerOfViewController(childViewController)
            }
        }

        return viewController
    }

}

0

IOS 9'da test edilen görünüm denetleyicisi yönünü kilitlemek için bunu kullanın:

// Yönü yatay sağa kilitle

-(UIInterfaceOrientationMask)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskLandscapeRight;
}

-(NSUInteger)navigationControllerSupportedInterfaceOrientations:(UINavigationController *)navigationController {
    return UIInterfaceOrientationMaskLandscapeRight;
}

0

Aynı problemim var ve bunun için çok fazla zaman harcıyorum. Şimdi benim çözümüm var. Benim uygulama ayar sadece destek portre.Ancak, benim app bazı ekranlar sadece manzara olması gerekir.IdDegate bir isShouldRotate bir değişkeni ile düzeltmek . Ve AppDelegate'teki işlev :

func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> Int {
    if isShouldRotate == true {
        return Int(UIInterfaceOrientationMask.Landscape.rawValue)
    }
    return Int(UIInterfaceOrientationMask.Portrait.rawValue)
}

Son olarak bir ViewControllerA yatay duruma ihtiyaç duyduğunda. Sadece bunu: itme / günümüze öncesi için ViewControllerA atama isShouldRotate için gerçek . / Pop atama o denetleyici görevden ne zaman unutma isShouldRotate için YANLıŞ de viewWillDisappear .


0

Benim için, üst düzey VC, yönlendirme geçersiz kılmalarını uygulamak için gerekliydi. Üst VC uygulanmıyorsa, VC'leri kullanarak yığının etkisi olmaz.

VC-main
    |
    -> VC 2
        |
        -> VC 3

Esasen testlerimde sadece VC-Main dinlenir.


0

Görünüşe göre burada çok fazla cevap var, kimse benim için yeterli değildi. Yönlendirmeyi zorlamak istedim ve geri dönüp cihaz yönüne geri döndüm ama [UIViewController attemptRotationToDeviceOrientation];işe yaramadı. Ne de karmaşık bir şey yaptım bazı cevap dayalı yanlış Autototate gerekir eklemiştir ve tüm senaryolarda doğru geri dönmek için istenen efektleri alamadım.

Ben de öyle yaptım:

Init yapıcısında çağrıda denetleyiciyi itmeden önce bu:

_userOrientation = UIDevice.currentDevice.orientation;
[UIDevice.currentDevice setValue:@(UIInterfaceOrientationPortrait) forKey:@"orientation"];
[self addNotificationCenterObserver:@selector(rotated:)
                               name:UIDeviceOrientationDidChangeNotification];

Bu yüzden son cihaz yönünü kaydediyorum ve yön değiştirme etkinliğine kaydoluyorum. Yön değiştirme olayı basittir:

- (void)rotated:(NSNotification*)notification {
    _userOrientation = UIDevice.currentDevice.orientation;
}

Ve görünümü kötüye kullanma üzerine ben sadece userOreintation olarak sahip olduğum herhangi bir yönelim zorlamak

- (void)onViewDismissing {
    super.onViewDismissing;
    [UIDevice.currentDevice setValue:@(_userOrientation) forKey:@"orientation"];
    [UIViewController attemptRotationToDeviceOrientation];
}

Ve bu da orada olmalı:

- (BOOL)shouldAutorotate {
    return true;
}

- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskPortrait;
}

Ayrıca, navigasyon denetleyicisinin AutoAtate ve supportInterfaceOrientations için yetki vermesi gerekir, ancak çoğu insanın zaten inanıyorum.

PS: Üzgünüm bazı uzantıları ve temel sınıfları kullanıyorum ama isimler oldukça anlamlı, bu yüzden konsept anlaşılabilir, daha fazla uzantı yapacak, çünkü şimdi çok güzel değil.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.