development

방향 변경을 감지하는 방법?

big-blog 2020. 6. 22. 07:18
반응형

방향 변경을 감지하는 방법?


Swift를 사용하고 있으며 가로로 회전 할 때 UIViewController를로드 할 수 있기를 원합니다. 누가 올바른 방향으로 나를 가리킬 수 있습니까?

온라인에서 찾을 수 없으며 설명서에 약간 혼란 스러울 수 있습니다.


작동 방식은 다음과 같습니다.

에서 AppDelegate.swift안쪽 didFinishLaunchingWithOptions내가 넣어 기능 :

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

그런 다음 AppDelegate 클래스 안에 다음 함수를 추가했습니다.

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

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

}

이것이 다른 누군가를 돕기를 바랍니다!

감사!


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. 대신 클로저를 사용하면이를 피할 수 있으며 이제 잘못된 선택기를 호출하여 충돌을 피해야하는 솔루션이 생겼습니다.

아래 코드는 XCode 10 및 iOS 4.2에서 더 이상 사용되지 않습니다.

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.
인터페이스 방향을 감지하는 데 사용할 수있는 두 가지 옵션이 있습니다.

  • 상태 표시 줄 방향 사용
  • 재정의되지 않은 경우 iPhone에서 크기 클래스를 사용하면 현재 인터페이스 방향을 이해할 수 있습니다.

여전히 누락 된 것은 인터페이스 방향의 변경 방향을 이해하는 방법이며, 이는 애니메이션 중에 매우 중요합니다.
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)
    }

새로운 viewWillTransitionToSize (_ : withTransitionCoordinator :)를 사용하십시오.


목표 C에서

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

신속하게

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

방향 변경을 감지하려면이 방법을 재정의하십시오.


스위프트 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 upface 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")
        }
    }

}

주의해야 할 중요한 사항은 다음과 같습니다.

  1. DeviceOrientationDidChange 알림 스트림을 수신하고이를 deviceOrientationDidChange 함수에 연결합니다.
  2. 그런 다음 장치 방향을 켜고 방향이 있는지 확인하십시오 unknown.
  3. 다른 알림과 마찬가지로 viewController가 초기화되기 전에 알림 스트림 관찰을 중지해야합니다.

누군가가 이것이 도움이되기를 바랍니다.


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 :

    //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
    }

다음과 같이 회전이 변경되었는지 확인하십시오. 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
        }
    }

회전이 완료된 후 무언가를 원한다면 다음 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`
    })
}

스위프트 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
    }
}

다양한 뷰 컨트롤러에서 감지해야 할 때 많은 답변이 도움이되지 않습니다. 이것은 트릭을 수행합니다.


내 접근 방식은 위의 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
    }
}

- (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... 

}

참고 URL : https://stackoverflow.com/questions/25666269/how-to-detect-orientation-change

반응형