webentwicklung-frage-antwort-db.com.de

Wie erkennt man Orientierungsänderungen?

Ich verwende Swift und möchte einen UIViewController laden können, wenn ich mich im Querformat bewege. Kann mir jemand die richtige Richtung zeigen?

Ich kann nichts online finden und durch die Dokumentation etwas verwirrt.

124
David

So habe ich es zum Laufen gebracht:

In AppDelegate.Swift in der didFinishLaunchingWithOptions-Funktion stelle ich Folgendes ein:

NotificationCenter.default.addObserver(self, selector: #selector(AppDelegate.rotated), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)

und dann in die AppDelegate-Klasse habe ich die folgende Funktion eingefügt: 

func rotated() {
    if UIDeviceOrientationIsLandscape(UIDevice.current.orientation) {
        print("Landscape")
    }

    if UIDeviceOrientationIsPortrait(UIDevice.current.orientation) {
        print("Portrait")
    }

}

Hoffe, das hilft allen anderen!

Vielen Dank!

177
David
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    if UIDevice.current.orientation.isLandscape {
        print("Landscape")
    } else {
        print("Portrait")
    }
}
163

Die Rotation muss während der Verwendung der Kamera mit AVFoundation erkannt werden, und es wurde festgestellt, dass die Methoden didRotate (now deprecated) & willTransition für meine Bedürfnisse unzuverlässig waren. Die von David gesendete Benachrichtigung hat funktioniert, ist aber für Swift 3.x/4.x nicht aktuell.

Swift 4.2 Der Benachrichtigungsname wurde geändert.

Der Abschlusswert bleibt der gleiche wie bei Swift 4.0:

var didRotate: (Notification) -> Void = { notification in
        switch UIDevice.current.orientation {
        case .landscapeLeft, .landscapeRight:
            print("landscape")
        case .portrait, .portraitUpsideDown:
            print("Portrait")
        default:
            print("other")
        }
    }

So richten Sie die Benachrichtigung für Swift 4.2 ein:

NotificationCenter.default.addObserver(forName: UIDevice.orientationDidChangeNotification,
                                       object: nil,
                                       queue: .main,
                                       using: didRotate)

So entfernen Sie die Benachrichtigung für Swift 4.2:

NotificationCenter.default.removeObserver(self,
                                          name: UIDevice.orientationDidChangeNotification,
                                          object: nil)

Bezüglich der Deprecation-Anweisung war mein erster Kommentar irreführend, daher wollte ich das aktualisieren. Wie bereits erwähnt, wurde die Verwendung von @objc-Inferenz aufgegeben, was wiederum für die Verwendung eines #selector erforderlich war. Wenn Sie stattdessen eine Schließung verwenden, kann dies vermieden werden, und Sie haben jetzt eine Lösung, die einen Absturz durch Aufrufen eines ungültigen Selektors vermeiden sollte.

Alles, was hier unten ist, ist seit XCode 10 und iOS 4.2 veraltet

Swift 4.0 Mit Swift 4.0 hat Apple uns aufgefordert, den #selector zu vermeiden, sodass dieser Ansatz jetzt einen Abschlussblock verwendet. Dieser Ansatz ist auch abwärtskompatibel mit Swift 3.x und wäre der empfohlene Ansatz für die Zukunft.

Dies ist die Compiler-Warnung, die Sie in einem Swift 4.x-Projekt erhalten, wenn Sie die #selector-Funktion verwenden, da @objc-Inferenz nicht mehr verwendet wird:

 enter image description here

Eintrag in der Swift-Evolution zu dieser Veränderung .

Richten Sie den Rückruf ein:

// If you do not use the notification var in your callback, 
// you can safely replace it with _
    var didRotate: (Notification) -> Void = { notification in
        switch UIDevice.current.orientation {
        case .landscapeLeft, .landscapeRight:
            print("landscape")
        case .portrait, .portraitUpsideDown:
            print("Portrait")
        default:
            print("other")
        }
    }

Richten Sie die Benachrichtigung ein:

NotificationCenter.default.addObserver(forName: .UIDeviceOrientationDidChange,
                                       object: nil,
                                       queue: .main,
                                       using: didRotate)

Reiß es nieder:

NotificationCenter.default.removeObserver(self, name: .UIDeviceOrientationDidChange, object: nil)
48
CodeBender

Die Verwendung der -orientation-Eigenschaft von UIDevice ist nicht korrekt (selbst wenn dies in den meisten Fällen funktionieren könnte) und könnte zu einigen Fehlern führen. Beispielsweise UIDeviceOrientation berücksichtigt auch die Ausrichtung des Geräts, wenn es nach oben oder unten zeigt. Es gibt kein direktes Paar UIInterfaceOrientation Aufzählung für diese Werte.
Wenn Sie Ihre App in einer bestimmten Ausrichtung sperren, gibt UIDevice die Ausrichtung des Geräts an, ohne dies zu berücksichtigen.
Auf der anderen Seite hat iOS8 die interfaceOrientation -Eigenschaft der UIViewController-Klasse nicht mehr unterstützt. 
Es gibt zwei Optionen, um die Schnittstellenorientierung zu erkennen:

  • Verwenden Sie die Statusleistenausrichtung
  • Verwenden Sie Größenklassen. Wenn sie auf dem iPhone nicht überschrieben werden, können Sie die aktuelle Schnittstellenorientierung besser verstehen.

Was noch fehlt, ist ein Weg, um die Richtung einer Änderung der Schnittstellenorientierung zu verstehen, die während Animationen sehr wichtig ist.
In der Sitzung der WWDC 2014 "View Controller Advancement in iOS8" bietet der Lautsprecher auch eine Lösung für dieses Problem, indem er die Methode verwendet, die -will/DidRotateToInterfaceOrientation ersetzt. 

Hier die vorgeschlagene Lösung teilweise umgesetzt, mehr Infos hier

func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
        let orientation = orientationFromTransform(coordinator.targetTransform())
        let oldOrientation = UIApplication.sharedApplication().statusBarOrientation
        myWillRotateToInterfaceOrientation(orientation,duration: duration)
        coordinator.animateAlongsideTransition({ (ctx) in
            self.myWillAnimateRotationToInterfaceOrientation(orientation,
            duration:duration)
            }) { (ctx) in
                self.myDidAnimateFromInterfaceOrientation(oldOrientation)
        }
    }
17
Andrea

Einfach, das funktioniert in iOS8 und 9/Swift 2/Xcode7, fügen Sie diesen Code einfach in Ihren viewcontroller.Swift ein. Bei jeder Änderung der Ausrichtung werden die Bildschirmabmessungen gedruckt. Sie können stattdessen Ihren eigenen Code eingeben:

override func didRotateFromInterfaceOrientation(fromInterfaceOrientation: UIInterfaceOrientation) {
        getScreenSize()
    }
    var screenWidth:CGFloat=0
    var screenHeight:CGFloat=0
    func getScreenSize(){
        screenWidth=UIScreen.mainScreen().bounds.width
        screenHeight=UIScreen.mainScreen().bounds.height
        print("SCREEN RESOLUTION: "+screenWidth.description+" x "+screenHeight.description)
    }
11
Josh

Ich weiß, dass diese Frage für Swift ist, aber da dies einer der Top-Links für eine Google-Suche ist und Sie denselben Code in Objective-C suchen:

// add the observer
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(rotated:) name:UIDeviceOrientationDidChangeNotification object:nil];

// remove the observer
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIDeviceOrientationDidChangeNotification object:nil];

// method signature
- (void)rotated:(NSNotification *)notification {
    // do stuff here
}
9
mikeho
9

Swift 3 | UIDeviceOrientationDidChange-Benachrichtigung zu oft beobachtet

Der folgende Code druckt "deviceDidRotate" jedes Mal, wenn Ihr Gerät die Ausrichtung im 3D-Raum ändert - unabhängig von einer Änderung von Hochformat zu Querformat. Wenn Sie beispielsweise Ihr Telefon im Hochformat halten und nach vorne und hinten kippen, wird deviceDidRotate () wiederholt aufgerufen.

override func viewDidLoad() {
    super.viewDidLoad()
    NotificationCenter.default.addObserver(
        self, 
        selector:  #selector(deviceDidRotate), 
        name: .UIDeviceOrientationDidChange, 
        object: nil
    )
}

func deviceDidRotate() {
    print("deviceDidRotate")
}

Um dies zu umgehen, können Sie die vorherige Ausrichtung des Geräts beibehalten und nach einer Änderung in deviceDidRotate () suchen.

var previousDeviceOrientation: UIDeviceOrientation = UIDevice.current.orientation

override func viewDidLoad() {
    super.viewDidLoad()
    NotificationCenter.default.addObserver(
        self, 
        selector:  #selector(deviceDidRotate), 
        name: .UIDeviceOrientationDidChange, 
        object: nil
    )
}

func deviceDidRotate() {
    if UIDevice.current.orientation == previousDeviceOrientation { return }
    previousDeviceOrientation = UIDevice.current.orientation
    print("deviceDidRotate")
}

Sie können auch eine andere Benachrichtigung verwenden, die nur dann aufgerufen wird, wenn das Gerät von Querformat zu Hochformat wechselt. In diesem Fall möchten Sie die Benachrichtigung UIApplicationDidChangeStatusBarOrientation verwenden.

override func viewDidLoad() {
    super.viewDidLoad()
    NotificationCenter.default.addObserver(
        self, 
        selector:  #selector(deviceDidRotate), 
        name: .UIApplicationDidChangeStatusBarOrientation, 
        object: nil
    )
}

func deviceDidRotate() {
    print("deviceDidRotate")
}
8
Derek Soike

In Ziel C

-(void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator

In Swift

func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator)

Überschreiben Sie diese Methode, um die Orientierungsänderung zu erkennen.

7
Mahendra GP
override func didRotate(from fromInterfaceOrientation: UIInterfaceOrientation) {
    //Swift 3
    getScreenSize()
}


func getScreenSize(){
   let screenWidth = UIScreen.main.bounds.width
   let  screenHeight = UIScreen.main.bounds.height
    print("SCREEN RESOLUTION: \(screenWidth.description) x \(screenHeight.description)")
}
5
Jeet Gandhi

Vollständige Implementierung der Erkennung von Orientierungsänderungen in Swift 3.0.

Ich habe mich für diese Implementierung entschieden, weil die Ausrichtung von face up und face down für mich wichtig war und ich wollte, dass sich die Ansicht erst ändert, wenn ich wusste, dass die Ausrichtung in der angegebenen Position war. 

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        //1
        NotificationCenter.default.addObserver(self, selector: #selector(deviceOrientationDidChange), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)

    }

    deinit {
        //3
        NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)
    }

    func deviceOrientationDidChange() {
        //2
        switch UIDevice.current.orientation {
        case .faceDown:
            print("Face down")
        case .faceUp:
            print("Face up")
        case .unknown:
            print("Unknown")
        case .landscapeLeft:
            print("Landscape left")
        case .landscapeRight:
            print("Landscape right")
        case .portrait:
            print("Portrait")
        case .portraitUpsideDown:
            print("Portrait upside down")
        }
    }

}

Die wichtigsten zu beachtenden Stücke sind:

  1. Sie hören den DeviceOrientationDidChange-Benachrichtigungsstream und verknüpfen ihn mit der Funktion deviceOrientationDidChange
  2. Sie schalten dann die Geräteorientierung ein, und stellen Sie sicher, dass zuweilen eine unknown-Ausrichtung vorliegt.
  3. Stellen Sie sicher, dass Sie den Benachrichtigungs-Stream nicht mehr beobachten, bevor der viewController desitialisiert wird.

Hoffe, jemand findet das hilfreich.

5
Rob Norback

Hier ist eine einfache Möglichkeit, die Ausrichtung des Geräts zu erkennen: ( Swift 3 )

override func willRotate(to toInterfaceOrientation: UIInterfaceOrientation, duration: TimeInterval) {
            handleViewRotaion(orientation: toInterfaceOrientation)
        }

    //MARK: - Rotation controls
    func handleViewRotaion(orientation:UIInterfaceOrientation) -> Void {
        switch orientation {
        case .portrait :
            print("portrait view")
            break
        case .portraitUpsideDown :
            print("portraitUpsideDown view")
            break
        case .landscapeLeft :
            print("landscapeLeft view")
            break
        case .landscapeRight :
            print("landscapeRight view")
            break
        case .unknown :
            break
        }
    }
4
Ram Madhavan

Prüfen Sie, ob sich die Rotation geändert hat: viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator)

Mit der coordinator.animateAlongsideTransition(nil) { (UIViewControllerTransitionCoordinatorContext) können Sie überprüfen, ob der Übergang abgeschlossen ist.

Siehe Code unten:

override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {

    super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)

    coordinator.animateAlongsideTransition(nil) { (UIViewControllerTransitionCoordinatorContext) in
        // if you want to execute code after transition finished
        print("Transition finished")
    }

    if size.height < size.width {
        // Landscape
        print("Landscape")
    } else {
        // Portrait
        print("Portrait")
    }

}
4
SDW

Ich überprüfe gerne die Orientierungsbenachrichtigung, da Sie diese Funktion in jeder Klasse hinzufügen können. Es muss keine Ansicht oder ein Ansichtscontroller sein. Auch in Ihrer App delegieren.

    //ask the system to start notifying when interface change
    UIDevice.currentDevice().beginGeneratingDeviceOrientationNotifications()
    //add the observer
    NSNotificationCenter.defaultCenter().addObserver(
        self,
        selector: #selector(self.orientationChanged(_:)),
        name: UIDeviceOrientationDidChangeNotification,
        object: nil)

als die Benachrichtigung zwischenspeichern

    func orientationChanged(notification : NSNotification) {
        //your code there
    }
3

Wenn Sie nach Abschluss der Rotation etwas tun möchten, können Sie den UIViewControllerTransitionCoordinator Completion-Handler wie folgt verwenden

public override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    super.viewWillTransition(to: size, with: coordinator)

    // Hook in to the rotation animation completion handler
    coordinator.animate(alongsideTransition: nil) { (_) in
        // Updates to your UI...
        self.tableView.reloadData()
    }
}
3
David Pettigrew

Für Swift 3

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    if UIDevice.current.orientation.isLandscape {
        //Landscape
    }
    else {
        //Portrait
    }
}
2
Mamta

Mein Ansatz ist ähnlich zu dem, was bpedit oben zeigt, aber mit einem Fokus auf iOS 9+. Ich wollte den Umfang des FSCalendar ändern, wenn sich die Ansicht dreht.

override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
    super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)

    coordinator.animateAlongsideTransition({ (context) in
        if size.height < size.width {
            self.calendar.setScope(.Week, animated: true)
            self.calendar.appearance.cellShape = .Rectangle
        }
        else {
            self.calendar.appearance.cellShape = .Circle
            self.calendar.setScope(.Month, animated: true)

        }

        }, completion: nil)
}

Das hat unten funktioniert, aber ich fühlte mich verlegen :)

coordinator.animateAlongsideTransition({ (context) in
        if size.height < size.width {
            self.calendar.scope = .Week
            self.calendar.appearance.cellShape = .Rectangle
        }
        }) { (context) in
            if size.height > size.width {
                self.calendar.scope = .Month
                self.calendar.appearance.cellShape = .Circle
            }
    }
2

Ich verwende UIUserInterfaceSizeClass, um eine in einer UIViewController-Klasse geänderte Ausrichtung genau so zu erkennen:

override func willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator) {

    let isiPadLandscapePortrait = newCollection.horizontalSizeClass == .regular && newCollection.verticalSizeClass == .regular
    let isiPhonePlustLandscape = newCollection.horizontalSizeClass == .regular && newCollection.verticalSizeClass == .compact
    let isiPhonePortrait = newCollection.horizontalSizeClass == .compact && newCollection.verticalSizeClass == .regular
    let isiPhoneLandscape = newCollection.horizontalSizeClass == .compact && newCollection.verticalSizeClass == .compact

     if isiPhonePortrait {
         // do something...
     }
}
2
pableiros

Swift 4:

override func viewWillAppear(_ animated: Bool) {
    NotificationCenter.default.addObserver(self, selector: #selector(deviceRotated), name: UIDevice.orientationDidChangeNotification, object: nil)
}

override func viewWillDisappear(_ animated: Bool) {
    NotificationCenter.default.removeObserver(self, name: UIDevice.orientationDidChangeNotification, object: nil)
}

@objc func deviceRotated(){
    if UIDevice.current.orientation.isLandscape {
        //Code here
    } else {
        //Code here
    }
}

Viele Antworten helfen nicht, wenn verschiedene Sichtsteuerungen erkannt werden müssen. Dieser macht den Trick.

2
Joel

Seit iOS 8 ist dies der richtige Weg.

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    super.viewWillTransition(to: size, with: coordinator)

    coordinator.animate(alongsideTransition: { context in
        // This is called during the animation
    }, completion: { context in
        // This is called after the rotation is finished. Equal to deprecated `didRotate`
    })
}
2
PatrickDotStar
- (void)viewDidLoad {
  [super viewDidLoad];
  [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(OrientationDidChange:) name:UIDeviceOrientationDidChangeNotification object:nil];
}

-(void)OrientationDidChange:(NSNotification*)notification {
  UIDeviceOrientation Orientation=[[UIDevice currentDevice]orientation];

  if(Orientation==UIDeviceOrientationLandscapeLeft || Orientation==UIDeviceOrientationLandscapeRight) {
    NSLog(@"Landscape");
  } else if(Orientation==UIDeviceOrientationPortrait) {
    NSLog(@"Potrait Mode");
  }
}

ANMERKUNG: Verwenden Sie diesen Code, um festzustellen, in welcher Richtung sich UIViewController befindet

0
Mannam Brahmam