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")
}
}
스위프트 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)
deprecation statement와 관련하여 초기 의견이 잘못되어서 업데이트하고 싶었습니다. 언급 한 바와 같이, @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
.
인터페이스 방향을 감지하는 데 사용할 수있는 두 가지 옵션이 있습니다.
여전히 누락 된 것은 인터페이스 방향의 변경 방향을 이해하는 방법이며, 이는 애니메이션 중에 매우 중요합니다.
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
있지만 Google 검색의 최상위 링크 중 하나이며 동일한 코드를 찾고 있다면 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:
작동합니다.
어느 클래스에서나이 기능을 추가 할 수 있기 때문에 방향 알림을 확인하는 것이 좋습니다. 뷰 또는 뷰 컨트롤러 일 필요는 없습니다. 앱 위임에서도.
스위프트 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
}
스위프트 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
}
}
다양한 뷰 컨트롤러에서 감지해야 할 때 많은 답변이 도움이되지 않습니다. 이것은 트릭을 수행합니다.
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...
}
}
스위프트 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...
}