私はSwiftを使用していて、横向きに回転したときにUIViewControllerをロードできるようにしたいのですが、誰かが私を正しい方向に向けることができますか?
オンラインでは何も見つからず、ドキュメントに少し混乱しています。
私はSwiftを使用していて、横向きに回転したときにUIViewControllerをロードできるようにしたいのですが、誰かが私を正しい方向に向けることができますか?
オンラインでは何も見つからず、ドキュメントに少し混乱しています。
回答:
これが私がそれを機能させた方法です:
でAppDelegate.swift
内部のdidFinishLaunchingWithOptions
機能私は置きます:
NotificationCenter.default.addObserver(self, selector: #selector(AppDelegate.rotated), name: UIDevice.orientationDidChangeNotification, object: nil)
次に、AppDelegateクラス内に次の関数を配置します。
func rotated() {
if UIDeviceOrientationIsLandscape(UIDevice.current.orientation) {
print("Landscape")
}
if UIDeviceOrientationIsPortrait(UIDevice.current.orientation) {
print("Portrait")
}
}
これが他の誰にも役立つことを願っています!
ありがとう!
selector
ですが、文字列形式にするべきではありません"rotated:"
か?
rotated()
います(受け入れません)
UIDeviceOrientation
は異なるので注意してくださいUIInterfaceOrientation
。これはUIDeviceOrientation
、デバイスがほぼ平らであるがわずかにでこぼこのある表面(つまり、突出部で揺れる)に置かれている場合、コードが縦向きと横向きをランダムにジャンプすることを意味します。 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")
}
}
でカメラを使用しているときに回転を検出する必要AVFoundation
があり、didRotate
(現在は非推奨)&willTransition
メソッドは私のニーズに信頼できないことがわかりました。Davidによって投稿された通知を使用することは機能しましたが、Swift 3.x / 4.xの最新ではありません。
Swift 4.2 通知名が変更されました。
クロージャ値は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")
}
}
Swift 4.2の通知を設定するには:
NotificationCenter.default.addObserver(forName: UIDevice.orientationDidChangeNotification,
object: nil,
queue: .main,
using: didRotate)
Swift 4.2の通知を破棄するには:
NotificationCenter.default.removeObserver(self,
name: UIDevice.orientationDidChangeNotification,
object: nil)
廃止に関する声明に関して、私の最初のコメントは誤解を招くものでしたので、それを更新したいと思いました。前述のように、@objc
推論の使用は非推奨になりました。これは、を使用するために必要でした#selector
。代わりにクロージャーを使用することにより、これを回避でき、無効なセレクターを呼び出すことによるクラッシュを回避するソリューションが得られます。
Swift 4.0
Swift 4.0では、Appleはを使用しないことを推奨しているため#selector
、このアプローチでは現在完了ブロックを使用しています。このアプローチはSwift 3.xとの下位互換性もあり、今後推奨されるアプローチです。
これは、推論#selector
の非推奨のために関数を使用した場合にSwift 4.xプロジェクトで受け取るコンパイラの警告です@objc
。
コールバックを設定します。
// 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")
}
}
通知を設定します。
NotificationCenter.default.addObserver(forName: .UIDeviceOrientationDidChange,
object: nil,
queue: .main,
using: didRotate)
それを取り壊します:
NotificationCenter.default.removeObserver(self, name: .UIDeviceOrientationDidChange, object: nil)
-orientation
プロパティの使用UIDevice
は正しくなく(ほとんどの場合に機能する可能性があります)、いくつかのバグにつながる可能性があります。たとえばUIDeviceOrientation
、デバイスが上向きまたは下向きの場合、デバイスの向きも考慮します。UIInterfaceOrientation
それらの列挙型には直接のペアはありません。値。
さらに、特定の向きでアプリをロックすると、UIDeviceはそれを考慮せずにデバイスの向きを提供します。
一方、iOS8はクラスのinterfaceOrientation
プロパティを廃止しましたUIViewController
。
インターフェイスの方向を検出するために使用できる2つのオプションがあります。
まだ欠けているのは、アニメーション中に非常に重要な、インターフェースの向きの変化の方向を理解する方法です。
WWDC 2014のセッション「iOS8でのビューコントローラーの進歩」では、スピーカーは、に代わる方法を使用して、この問題の解決策も提供します -will/DidRotateToInterfaceOrientation
。
ここで提案されたソリューションは部分的に実装されました、詳細はこちら:
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)
}
}
私はこの質問をするために知っているSwift
あなたは同じコードで探しているなら、それはグーグルのトップのリンクのいずれかをだから検索して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
}
簡単です。これはiOS8および9 / Swift 2 / Xcode7で機能します。このコードをviewcontroller.swift内に配置するだけです。向きが変わるたびに画面の寸法が出力されます。代わりに独自のコードを配置できます。
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()
確実に機能しません。いくつかの回転を逃します。iewWillTransitionToSize:withTransitionCoordinator:
大丈夫です。
この機能はどのクラスにも追加できるため、方向通知を確認するのが好きです。ビューやビューコントローラである必要はありません。アプリのデリゲートでも。
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)
通知をキャッシュするより
@objc func orientationChanged(notification : NSNotification) {
//your code there
}
Swift 3 | 頻繁に監視されるUIDeviceOrientationDidChange通知
次のコードは、縦向きから横向きへの変更に関係なく、デバイスが3D空間で向きを変更するたびに「deviceDidRotate」を出力します。たとえば、スマートフォンを縦向きにして、前後に傾けると、deviceDidRotate()が繰り返し呼び出されます。
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(
self,
selector: #selector(deviceDidRotate),
name: .UIDeviceOrientationDidChange,
object: nil
)
}
func deviceDidRotate() {
print("deviceDidRotate")
}
これを回避するには、以前のデバイスの向きを保持し、deviceDidRotate()の変更を確認します。
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")
}
または、デバイスが横向きから縦向きに変わったときにのみ呼び出される別の通知を使用することもできます。この場合、UIApplicationDidChangeStatusBarOrientation
通知を使用します。
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(
self,
selector: #selector(deviceDidRotate),
name: .UIApplicationDidChangeStatusBarOrientation,
object: nil
)
}
func deviceDidRotate() {
print("deviceDidRotate")
}
Swift 3.0で向きの変化を検出する方法の完全に機能する実装。
私は、の電話の向きため、この実装を使用することを選んだface up
とface down
私にとって重要だった、と私は向きが指定された位置に知っていた後、私は変更するビューを望んでいました。
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")
}
}
}
注意すべき重要な部分は次のとおりです。
unknown
。向きが時々あることに注意してください。これが役に立ったと誰かが願っています。
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)")
}
回転が完了したUIViewControllerTransitionCoordinator
後で何かしたい場合は、次のような完了ハンドラを使用できます
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()
}
}
iOS 8以降、これが正しい方法です。
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`
})
}
ローテーションが変更されたかどうかを確認します。 viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator)
を使用してcoordinator.animateAlongsideTransition(nil) { (UIViewControllerTransitionCoordinatorContext)
、移行が終了したかどうかを確認できます。
以下のコードを参照してください。
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")
}
}
デバイスの向きを検出する簡単な方法を次に示します:(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
は非推奨になりましたviewWillTransition
。より適切に使用してください。
スウィフト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
}
}
さまざまなView Controllerを検出する必要がある場合、多くの回答が役に立ちません。これはトリックを行います。
viewWillDisappear
し、追加addObserver
の中でviewDidLoad
。iOSは自動的にView Controllerの登録を解除します。
UIDevice.current.orientation.isFlat
私のアプローチはbpeditが上に示したものと似ていますが、iOS 9以降に重点を置いています。ビューが回転したときにFSCalendarのスコープを変更したいと思いました。
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)
}
これはうまくいきましたが、私はそれについてひどく感じました:)
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
}
}
私はそのようなクラスでUIUserInterfaceSizeClass
変更された方向を検出するために使用しますUIViewController
:
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...
}
}
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
スウィフト5
デバイスの向きの変更の通知を受け取るセットアップクラス:
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)
...
}
...
}
セットアップハンドラーコード:
@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");
}
}
注:このコードを使用して、UIViewControllerがどの方向にあるかを識別します
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...
}