[iPhone] iOS6 회전 지원하기

아이폰 2013. 1. 25. 01:17



iOS6.0 부터 회전을 지원하는 delegate 메소드가 조금 변경되었습니다.


iOS6.0 업데이트 후 회전이 올바로 동작하지 않는 것을 보고 적잖이 당황했었습니다. 


관련내용을 찾아보니 의외로 어렵지 않게 6.0에서도 회전에 대응할 수 있었습니다~ 


그럼 6.0 이상 및 하위버전에서 회전을 올바로 지원하기 위한방법에 대해서 알아봅시다





홈 버튼을 기준으로 왼쪽으로 회전, 오른쪽으로 회전, 거꾸로 뒤집었을 때 등 각 방향을 지칭하게 됩니다!








먼저 기존에는 회전을 지원하기 위해 아래와 같은 스텝을 거쳤습니다.



1. Window에 View 추가 


[self.window addSubview:viewController.view]




2. UIViewController 에 지원 회전방향 delegate 구현 


// 자동회전 지원하는 방향 
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    return (interfaceOrientation == UIInterfaceOrientationPortrait || 
               interfaceOrientation == UIInterfaceOrientationLandscapeLeft ||            
               interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}



3. UIViewController 에서 회전하기 전/후 호출되는 delegate 구현 


- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
    // 회전하기 전에 호출됩니다.
}

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
   // 회전 후에 호출됩니다.
}



shouldAutorotateToInterfaceOrientation의 UIInterfaceOrentation 파라미터 타입은 다음과 같이 

enum 타입 상수로  선언되어 있습니다.


typedef NS_ENUM(NSInteger, UIInterfaceOrientation) {
    UIInterfaceOrientationPortrait           = UIDeviceOrientationPortrait,
    UIInterfaceOrientationPortraitUpsideDown = UIDeviceOrientationPortraitUpsideDown,
    UIInterfaceOrientationLandscapeLeft      = UIDeviceOrientationLandscapeRight,
    UIInterfaceOrientationLandscapeRight     = UIDeviceOrientationLandscapeLeft
};




iOS 6.0 에서는 무엇을 바뀌었을까요?



iOS6.0에서는 1번과 2번 스텝이 변경되었습니다. 




1. Window에 rootViewController 추가 


self.window.rootViewController = viewController;


기존에는 Window의 View를 추가했지만, iOS6.0 부터는 반드시 Window의 rootViewController로 지정해야 합니다. 





2. UIViewController 에 지원 회전방향 delegate 구현 


//  자동회전 지원 유무 
- (BOOL) shouldAutorotate {
      return YES; 
}
// 지원하는 회전방향 
- (NSUInteger)supportedInterfaceOrientations {
    return (1 << UIInterfaceOrientationPortrait) | (1 << UIInterfaceOrientationLandscapeLeft) | (1 << UIInterfaceOrientationLandscapeRight);
}




기존에 2가지 역할을 하던 메소드가 자동회전 유무와 회전하는 방향을 반환하는 메소드로 각각 분리되었습니다.


또 지원하는 회전방향의 경우,  NSUInterger 반환값으로 변경되었는데 이 값은 지원하는 회전방향의 비트가 셋팅된


비트 플래그 값입니다.


typedef NS_OPTIONS(NSUInteger, UIInterfaceOrientationMask) {
    UIInterfaceOrientationMaskPortrait = (1 << UIInterfaceOrientationPortrait),
    UIInterfaceOrientationMaskLandscapeLeft = (1 << UIInterfaceOrientationLandscapeLeft),
    UIInterfaceOrientationMaskLandscapeRight = (1 << UIInterfaceOrientationLandscapeRight),
    UIInterfaceOrientationMaskPortraitUpsideDown = (1 << UIInterfaceOrientationPortraitUpsideDown),
    UIInterfaceOrientationMaskLandscape = (UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight),
    UIInterfaceOrientationMaskAll = (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft |
                                                   UIInterfaceOrientationMaskLandscapeRight | UIInterfaceOrientationMaskPortraitUpsideDown),
    UIInterfaceOrientationMaskAllButUpsideDown = (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | 
                                                                         UIInterfaceOrientationMaskLandscapeRight),
};



1을 UIInterfaceOrentation 상수값 만큼 왼쪽으로 시프트해주면, 해당하는 방향의 비트를 셋팅할 수 있지요.



또 한가지 중요한 사항은, 커스텀 UINavigationController와 UITabBarController를 사용한 경우(상속해서)


이 커스텀 클래스의 회전 지원 delegate 메소드에서는 topViewController의 회전지원 delegate 메소드로 


위임해야 한다는 것입니다. 아래와 같이 말이죠!



...
- (BOOL) shouldAutorotate {
    return [topViewController shouldAutorotate];
}
...







다음은 iOS6.0 이상 및 미만에서 회전을 올바로 처리하기 위한 코드를 정리한 것입니다.



- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    ...
    // iOS6.0 이상
    NSString *currentVersion = [[UIDevice currentDevice] systemVersion];
    
    NSLog(@"%@", currentVersion);
    
    if ([currentVersion compare:@"6.0" options:NSNumericSearch] != NSOrderedAscending) {
        self.window.rootViewController = self.viewController;
    } else {
        // 하위버전
        [self.window addSubview:self.viewController.view];
    }
    [self.window makeKeyAndVisible];
    return YES;
}

#pragma mark - 회전지원 iOS6.0 이상

// 자동회전 지원유무
- (BOOL) shouldAutorotate {
    return YES;
}

// 회전방향 지원유무
- (NSUInteger)supportedInterfaceOrientations {
    return (1 << UIInterfaceOrientationPortrait) |
           (1 << UIInterfaceOrientationPortraitUpsideDown) |
           (1 << UIInterfaceOrientationLandscapeLeft) |
           (1 << UIInterfaceOrientationLandscapeRight);
}

#pragma mark - 회전지원 iOS6.0 미만 

// 회전방향 지원유무
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft ||
            interfaceOrientation == UIInterfaceOrientationLandscapeLeft ||
            interfaceOrientation == UIInterfaceOrientationLandscapeRight ||
            interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown
            );
}


#pragma mark - 회전 델리게이트 

// 공통
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
    // 회전하기 전에 호출됩니다.
}

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
    // 회전 후에 호출됩니다.
}




소스코드 다운로드

Rotation.zip