[ios] iOS 8에서 방향 변경을 처리하는 “올바른”방법은 무엇입니까?

누군가 iOS 8에서 세로 및 가로 인터페이스 방향으로 작업하는 데 “올바른”또는 “가장 좋은”접근 방식을 알려주시겠습니까? 그 목적으로 사용하려는 모든 기능이 iOS 8에서 더 이상 사용되지 않는 것 같습니다. 그리고 내 연구에 따르면 명확하고 우아한 대안이 없습니다. 가로 모드인지 세로 모드인지 스스로 결정하기 위해 너비와 높이를 확인해야합니까?

예를 들어, 뷰 컨트롤러에서 다음 의사 코드를 어떻게 구현해야합니까?

if we are rotating from portrait to landscape then
  do portrait things
else if we are rotating from landscape to portrait then
  do landscape things



답변

Apple은 UI가 레이아웃과 모양을 크게 변경할 수 있도록 크기 클래스를 사용 가능한 화면 공간의 대략적인 척도로 사용할 것을 권장합니다. 세로 모드의 iPad는 가로 모드 (일반 너비, 일반 높이)와 동일한 크기 등급을 가지고 있다고 가정합니다. 이는 UI가 두 방향간에 다소 유사해야 함을 의미합니다.

그러나 iPad에서 세로에서 가로로의 변경은 크기 클래스가 변경되지 않았더라도 UI를 약간 조정해야 할만큼 충분히 중요합니다. 의 인터페이스 방향 관련 메서드 UIViewController가 더 이상 사용되지 않으므로 Apple은 이제 다음과 같은 새로운 메서드를 UIViewController대체로 구현할 것을 권장합니다 .

- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id <UIViewControllerTransitionCoordinator>)coordinator
{
    [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];

    // Code here will execute before the rotation begins.
    // Equivalent to placing it in the deprecated method -[willRotateToInterfaceOrientation:duration:]

    [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {

        // Place code here to perform animations during the rotation.
        // You can pass nil or leave this block empty if not necessary.

    } completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {

        // Code here will execute after the rotation has finished.
        // Equivalent to placing it in the deprecated method -[didRotateFromInterfaceOrientation:]

    }];
}

큰! 이제 순환이 시작되기 직전과 완료된 후에 콜백을받습니다. 그러나 회전이 세로인지 가로인지 실제로 아는 것은 어떨까요?

Apple은 회전을 단순히 상위 뷰의 크기 변경으로 생각할 것을 권장합니다. 즉, 세로에서 가로로 아이 패드 회전하는 동안, 당신은 루트 레벨보기는 단순히 변화로 생각할 수 bounds.size에서 {768, 1024}까지 {1024, 768}. 이를 알면 위 sizeviewWillTransitionToSize:withTransitionCoordinator:메서드에 전달 된를 사용하여 세로 또는 가로로 회전하는지 파악 해야합니다 .

레거시 코드를 새로운 iOS 8 방식으로 마이그레이션하는보다 원활한 방법을 원한다면 UIView 에서이 간단한 범주 를 사용하는 것이 좋습니다. 이 범주 를 사용하여 뷰가 “세로”인지 또는 “가로”인지 여부를 결정하는 데 사용할 수 있습니다. 크기.

요약하자면:

  1. 크기 클래스를 사용하여 근본적으로 다른 UI를 표시 할시기를 결정해야합니다 (예 : “iPhone과 유사한”UI 대 “iPad와 유사한”UI).
  2. iPad가 회전 할 때와 같이 크기 클래스 변경 되지 않고 컨테이너 (부모보기) 크기가 변경 될 때 UI를 더 작게 조정해야하는 경우 viewWillTransitionToSize:withTransitionCoordinator:UIViewController 에서 콜백을 사용하십시오 .
  3. 앱의 모든 뷰는 레이아웃에 주어진 공간에 따라 레이아웃을 결정해야합니다. 뷰의 자연스러운 계층 구조가이 정보를 계단식으로 배열하도록합니다.
  4. 마찬가지로 statusBarOrientation기본적으로 장치 수준 속성 인를 사용하여 “세로”와 “가로”보기를 레이아웃할지 여부를 결정 하지 마십시오 . 상태 표시 줄 방향은 UIWindow실제로 앱의 가장 루트 수준에있는 것과 같은 것을 처리하는 코드에서만 사용해야 합니다.

답변

smileyborg의 매우 상세한 (및 수용된) 답변을 기반으로하여 다음은 신속한 3을 사용한 적응입니다.

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    super.viewWillTransition(to: size, with: coordinator)
    coordinator.animate(alongsideTransition: nil, completion: {
        _ in
        self.collectionView.collectionViewLayout.invalidateLayout()
    })
}

그리고 UICollectionViewDelegateFlowLayout구현에서

public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    // retrieve the updated bounds
    let itemWidth = collectionView.bounds.width
    let itemHeight = collectionView.bounds.height
    // do whatever you need to do to adapt to the new size
}


답변

알림 센터를 사용합니다.

방향 변수 추가 (마지막에 설명)

//Above viewdidload
var orientations:UIInterfaceOrientation = UIApplication.sharedApplication().statusBarOrientation

보기가 나타날 때 알림 추가

override func viewDidAppear(animated: Bool) {
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "orientationChanged:", name: UIDeviceOrientationDidChangeNotification, object: nil)
}

보기가 사라질 때 알림 제거

override func viewWillDisappear(animated: Bool) {
        NSNotificationCenter.defaultCenter().removeObserver(self, name: UIDeviceOrientationDidChangeNotification, object: nil)
}

알림이 트리거 될 때 현재 방향을 가져옵니다.

func orientationChanged (notification: NSNotification) {
    adjustViewsForOrientation(UIApplication.sharedApplication().statusBarOrientation)
}

방향 (세로 / 가로) 확인 및 이벤트 처리

func adjustViewsForOrientation(orientation: UIInterfaceOrientation) {
    if (orientation == UIInterfaceOrientation.Portrait || orientation == UIInterfaceOrientation.PortraitUpsideDown)
    {
        if(orientation != orientations) {
            println("Portrait")
            //Do Rotation stuff here
            orientations = orientation
        }
    }
    else if (orientation == UIInterfaceOrientation.LandscapeLeft || orientation == UIInterfaceOrientation.LandscapeRight)
    {
       if(orientation != orientations) {
            println("Landscape")
            //Do Rotation stuff here
            orientations = orientation
        }
    }
}

방향 변수를 추가하는 이유는 물리적 장치에서 테스트 할 때 방향 알림이 회전 할 때뿐만 아니라 장치의 모든 사소한 움직임에서 호출되기 때문입니다. var 및 if 문을 추가하면 반대 방향으로 전환 된 경우에만 코드가 호출됩니다.


답변

UI 관점에서 저는 크기 클래스를 사용하는 것이 다양한 방향, 크기 및 스케일의 인터페이스를 처리하기 위해 Apple에서 권장하는 접근 방식이라고 생각합니다.

https://developer.apple.com/library/ios/releasenotes/General/WhatsNewIniOS/Articles/iOS8.html 에서 인터페이스의 크기 클래스 및 규모 설명 섹션을 참조 하십시오.

“iOS 8은 화면 크기와 방향을 훨씬 더 다양하게 다루는 새로운 기능을 추가합니다.”

이것도 좋은 기사입니다 :
https://carpeaqua.com/thinking-in-terms-of-ios-8-size-classes/


업데이트 된 링크 편집 :
https://carpeaqua.com/2014/06/14/thinking-in-terms-of-ios-8-size-classes/ (크레딧 : Koen)


답변