Ich verwende Swift und möchte einen UIViewController laden können, wenn ich mich in den Querformat drehe. Kann mich jemand in die richtige Richtung weisen?
Ich kann online nichts finden und bin durch die Dokumentation etwas verwirrt.
Ich verwende Swift und möchte einen UIViewController laden können, wenn ich mich in den Querformat drehe. Kann mich jemand in die richtige Richtung weisen?
Ich kann online nichts finden und bin durch die Dokumentation etwas verwirrt.
Antworten:
So habe ich es zum Laufen gebracht:
In AppDelegate.swift
die didFinishLaunchingWithOptions
Funktion habe ich eingefügt:
NotificationCenter.default.addObserver(self, selector: #selector(AppDelegate.rotated), name: UIDevice.orientationDidChangeNotification, object: nil)
und dann habe ich innerhalb der AppDelegate-Klasse die folgende Funktion eingefügt:
func rotated() {
if UIDeviceOrientationIsLandscape(UIDevice.current.orientation) {
print("Landscape")
}
if UIDeviceOrientationIsPortrait(UIDevice.current.orientation) {
print("Portrait")
}
}
Hoffe das hilft jemand anderem!
Vielen Dank!
selector
bin neu in der Codierung, sollte aber kein String-Format von "rotated:"
??
rotated()
nicht der Fall ist)
UIDeviceOrientation
etwas anderes ist als UIInterfaceOrientation
.. Dies liegt daran, dass UIDeviceOrientation
auch verdeckte und verdeckte Ausrichtungen erkannt werden, was bedeutet, dass Ihr Code zufällig zwischen Hoch- und Querformat wechseln kann, wenn Ihr Gerät auf einer fast flachen, aber leicht unebenen Oberfläche ruht (dh auf dem hervorstehenden Teil schaukelt) Kamera der 6 / 6s)
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
if UIDevice.current.orientation.isLandscape {
print("Landscape")
}
if UIDevice.current.orientation.isFlat {
print("Flat")
} else {
print("Portrait")
}
}
Ich musste eine Drehung erkennen, während ich die Kamera mit benutzte AVFoundation
, und stellte fest, dass die didRotate
( jetzt veralteten ) & willTransition
Methoden für meine Bedürfnisse unzuverlässig waren. Die Verwendung der von David geposteten Benachrichtigung hat funktioniert, ist jedoch für Swift 3.x / 4.x nicht aktuell.
Swift 4.2 Der Benachrichtigungsname wurde geändert.
Der Schließwert 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 brechen Sie die Benachrichtigung für Swift 4.2 ab :
NotificationCenter.default.removeObserver(self,
name: UIDevice.orientationDidChangeNotification,
object: nil)
In Bezug auf die Abschreibungserklärung war mein erster Kommentar irreführend, daher wollte ich ihn aktualisieren. Wie bereits erwähnt, wurde die Verwendung von @objc
Inferenz veraltet, was wiederum für die Verwendung von a erforderlich war #selector
. Durch die Verwendung eines Verschlusses kann dies vermieden werden, und Sie haben jetzt eine Lösung, die einen Absturz aufgrund des Aufrufs eines ungültigen Selektors vermeiden sollte.
Swift 4.0
Mit Swift 4.0 hat Apple uns ermutigt, die Verwendung von zu vermeiden. #selector
Daher verwendet dieser Ansatz jetzt einen Abschlussblock. Dieser Ansatz ist auch abwärtskompatibel mit Swift 3.x und wird in Zukunft empfohlen.
Dies ist die Compiler-Warnung, die Sie in einem Swift 4.x-Projekt erhalten, wenn Sie die #selector
Funktion aufgrund der veralteten @objc
Inferenz verwenden:
Einstieg in die schnelle Entwicklung zu dieser Ä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)
Die Verwendung der -orientation
Eigenschaft von UIDevice
ist nicht korrekt (auch wenn sie in den meisten Fällen funktionieren könnte) und kann zu einigen Fehlern führen. UIDeviceOrientation
Berücksichtigen Sie beispielsweise auch die Ausrichtung des Geräts, wenn es nach oben oder unten zeigt. Für diese gibt es kein direktes Paar in der UIInterfaceOrientation
Aufzählung Werte.
Wenn Sie Ihre App in einer bestimmten Ausrichtung sperren, gibt Ihnen UIDevice außerdem die Geräteorientierung, ohne dies zu berücksichtigen.
Auf der anderen Seite hat iOS8 die interfaceOrientation
Eigenschaft für die UIViewController
Klasse veraltet .
Es stehen 2 Optionen zur Verfügung, um die Ausrichtung der Benutzeroberfläche zu ermitteln:
Was noch fehlt, ist eine Möglichkeit, die Richtung einer Änderung der Schnittstellenorientierung zu verstehen, die bei Animationen sehr wichtig ist.
In der Sitzung der WWDC 2014 "View Controller Advancement in iOS8" bietet der Sprecher auch eine Lösung für dieses Problem mit der Methode, die ersetzt -will/DidRotateToInterfaceOrientation
.
Hier wurde die vorgeschlagene Lösung teilweise implementiert, weitere 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)
}
}
Ich weiß, dass diese Frage für ist Swift
, aber da es einer der Top-Links für eine Google-Suche ist und Sie nach dem gleichen Code suchen in Objective-C
:
// 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
}
Ganz einfach, dies 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)
}
didRotateFromInterfaceOrientation()
funktioniert es nicht zuverlässig. Es fehlen einige Umdrehungen. iewWillTransitionToSize:withTransitionCoordinator:
funktioniert ok
Verwenden Sie die neue viewWillTransitionToSize (_: withTransitionCoordinator :)
Ich überprüfe gerne die Orientierungsbenachrichtigung, da Sie diese Funktion in jeder Klasse hinzufügen können, ohne dass eine Ansicht oder ein Ansichtscontroller erforderlich ist. Auch in Ihrem App-Delegaten.
SWIFT 5:
//ask the system to start notifying when interface change
UIDevice.current.beginGeneratingDeviceOrientationNotifications()
//add the observer
NotificationCenter.default.addObserver(
self,
selector: #selector(orientationChanged(notification:)),
name: UIDevice.orientationDidChangeNotification,
object: nil)
als die Benachrichtigung zwischenzuspeichern
@objc func orientationChanged(notification : NSNotification) {
//your code there
}
In Ziel C.
-(void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
In kurzer Zeit
func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator)
Überschreiben Sie diese Methode, um die Orientierungsänderung zu erkennen.
Swift 3 | Zu oft beobachtete UIDeviceOrientationDidChange-Benachrichtigung
Der folgende Code druckt "deviceDidRotate" jedes Mal, wenn Ihr Gerät die Ausrichtung im 3D-Raum ändert - unabhängig von einer Änderung von Hoch- zu Querformat. Wenn Sie beispielsweise Ihr Telefon im Hochformat halten und es vorwärts und rückwärts neigen, 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 Geräteorientierung 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")
}
Oder Sie können eine andere Benachrichtigung verwenden, die nur aufgerufen wird, wenn das Gerät von Querformat zu Hochformat wechselt. In diesem Fall möchten Sie die UIApplicationDidChangeStatusBarOrientation
Benachrichtigung verwenden.
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(
self,
selector: #selector(deviceDidRotate),
name: .UIApplicationDidChangeStatusBarOrientation,
object: nil
)
}
func deviceDidRotate() {
print("deviceDidRotate")
}
Vollständige Implementierung der Erkennung von Orientierungsänderungen in Swift 3.0.
Ich habe mich für diese Implementierung entschieden, weil die Telefonausrichtungen von face up
und face down
für mich wichtig waren und ich wollte, dass sich die Ansicht erst ändert, wenn ich weiß, dass sich die Ausrichtung an der angegebenen Position befindet.
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:
unknown
manchmal eine Ausrichtung vorhanden ist .Hoffe jemand findet das hilfreich.
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)")
}
Wenn Sie etwas tun möchten, nachdem die Drehung abgeschlossen ist, können Sie den UIViewControllerTransitionCoordinator
Abschluss-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()
}
}
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`
})
}
Überprüfen Sie, ob sich die Drehung geändert hat mit: viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator)
Mit dem coordinator.animateAlongsideTransition(nil) { (UIViewControllerTransitionCoordinatorContext)
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")
}
}
Hier ist eine einfache Möglichkeit, die Geräteorientierung 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
}
}
willRotate
ist jetzt veraltet, besser nutzen viewWillTransition
.
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 sie über verschiedene Ansichts-Controller hinweg erkannt werden müssen. Dieser macht den Trick.
viewWillDisappear
und fügen Sie addObserver
in viewDidLoad
. iOS hebt den View Controller automatisch ab.
UIDevice.current.orientation.isFlat
Mein Ansatz ähnelt dem, was bpedit oben zeigt, jedoch mit einem Fokus auf iOS 9+. Ich wollte den Bereich 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 unten hat funktioniert, aber ich fühlte mich verlegen darüber :)
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
}
}
Ich benutze UIUserInterfaceSizeClass
, um eine Orientierung zu erkennen, die sich in einer UIViewController
Klasse einfach so geändert hat :
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...
}
}
Für Swift 3
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
if UIDevice.current.orientation.isLandscape {
//Landscape
}
else if UIDevice.current.orientation.isFlat {
//isFlat
}
else {
//Portrait
}
}
UIDevice.current.orientation.isFlat
Swift 5
Setup-Klasse zum Empfangen von Benachrichtigungen über Änderungen der Geräteorientierung:
class MyClass {
...
init (...) {
...
super.init(...)
// subscribe to device orientation change notifications
UIDevice.current.beginGeneratingDeviceOrientationNotifications()
NotificationCenter.default.addObserver(self, selector: #selector(orientationChanged), name: UIDevice.orientationDidChangeNotification, object: nil)
...
}
...
}
Setup-Handler-Code:
@objc extension MyClass {
func orientationChanged(_ notification: NSNotification) {
let device = notification.object as! UIDevice
let deviceOrientation = device.orientation
switch deviceOrientation {
case .landscapeLeft: //do something for landscape left
case .landscapeRight: //do something for landscape right
case .portrait: //do something for portrait
case .portraitUpsideDown: //do something for portrait upside-down
case .faceDown: //do something for face down
case .faceUp: //do something for face up
case .unknown: //handle unknown
@unknown default: //handle unknown default
}
}
}
- (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");
}
}
HINWEIS: Verwenden Sie einfach diesen Code, um zu identifizieren, in welcher Ausrichtung sich UIViewController befindet
override func viewDidLoad() {
NotificationCenter.default.addObserver(self, selector: #selector(MyController.rotated), name: UIDevice.orientationDidChangeNotification, object: nil)
//...
}
@objc
private func rotated() {
if UIDevice.current.orientation.isLandscape {
} else if UIDevice.current.orientation.isPortrait {
}
//or you can check orientation separately UIDevice.current.orientation
//portrait, portraitUpsideDown, landscapeLeft, landscapeRight...
}
Unter iOS 13.1.2 gibt die Ausrichtung immer 0 zurück, bis das Gerät gedreht wird. Ich muss UIDevice.current.beginGeneratingDeviceOrientationNotifications () aufrufen, um die tatsächliche Rotation abzurufen, bevor ein Rotationsereignis auftritt.