programing tip

iOS 6은 기기 방향을 가로로 강제

itbloger 2020. 12. 24. 23:23
반응형

iOS 6은 기기 방향을 가로로 강제


10 개의 뷰 컨트롤러가있는 앱을 제공했습니다. 내비게이션 컨트롤러를 사용하여로드 / 언로드합니다.

하나를 제외하고 모두 세로 모드입니다. 7 번째 VC가 가로 모드라고 가정합니다. 로드 될 때 가로로 표시되어야합니다.

IOS 6에서 방향을 세로에서 가로로 강제 전환하는 방법을 제안하십시오 (IOS 5에서도 작동하는 것이 좋을 것입니다).

여기에 내가 그 일을하고 어떻게 전에 IOS 6 :

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    UIViewController *c = [[[UIViewController alloc]init] autorelease];
    [self presentModalViewController:c animated:NO];
    [self dismissModalViewControllerAnimated:NO];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

모달 VC를 제시하고 닫으면 앱이 방향을 검토해야했기 때문에 shouldAutorotateToInterfaceOrientation호출 을 받았습니다 .

IOS 6에서 시도한 것 :

- (BOOL)shouldAutorotate{
    return YES;
}
-(NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskLandscape;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
    return UIInterfaceOrientationLandscapeLeft;
}

로드시 컨트롤러는 계속 세로로 유지됩니다. 장치를 회전하면 방향이 그대로 변경됩니다. 하지만 컨트롤러가로드시 자동으로 가로 방향으로 회전하도록 만들어야하므로 사용자가 데이터를 올바르게 보려면 장치를 회전해야합니다.

또 다른 문제 : 장치를 다시 세로로 회전 한 후에서 지정했지만 방향이 세로로 전환 supportedInterfaceOrientations됩니다 UIInterfaceOrientationMaskLandscape. 왜 발생합니까?

또한, NONE 위의 3 방법은 호출되지 얻고있다.

일부 (유용한) 데이터 :

  1. 내 plist 파일에서 거꾸로 된 3 가지 방향을 지정했습니다.
  2. 이 프로젝트는 Xcode 4.3 IOS 5에서 시작되었습니다. xib를 포함한 모든 클래스는 Xcode 4.5 IOS 6 이전에 생성되었으므로 이제 마지막 버전을 사용합니다.
  3. plist 파일에서 상태 표시 줄은 표시로 설정됩니다.
  4. xib 파일 (가로로 설정하려는 파일)에서 상태 표시 줄은 "없음"이고 방향은 가로로 설정됩니다.

도움을 주시면 감사하겠습니다. 감사.


좋아, 여러분, 내 솔루션을 게시 할 것입니다.

내가 가진 것 :

  1. 여러 뷰 컨트롤러가있는 뷰 기반 응용 프로그램입니다. (내비게이션 기반이지만 방향 문제로 인해보기 기반으로 만들어야했습니다).
  2. 모든 뷰 컨트롤러는 하나를 제외하고 세로입니다-landscapeLeft.

작업 :

  1. 내 뷰 컨트롤러 중 하나는 사용자가 장치를 잡는 방법에 관계없이 자동으로 가로 방향으로 회전해야합니다. 다른 모든 컨트롤러는 세로 여야하며 가로 컨트롤러를 떠난 후에는 사용자가 기기를 잡는 방식에 관계없이 앱이 강제로 세로로 회전해야합니다.
  2. 이것은 IOS 5.x에서와 같이 IOS 6.x에서 작동해야합니다.

가다!

( 업데이트 @Ivan Vučica가 제안한 매크로 제거)

모든 PORTRAIT 뷰 컨트롤러에서 다음과 같은 자동 회전 방법을 재정의합니다.

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation{
    return (toInterfaceOrientation == UIInterfaceOrientationPortrait);
}
-(BOOL)shouldAutorotate {
    return YES;
}
- (NSUInteger)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskPortrait;
}

두 가지 접근 방식을 볼 수 있습니다. 하나는 IOS 5 용이고 다른 하나는 IOS 6 용입니다.

LANDSCAPE 뷰 컨트롤러에도 동일하지만 몇 가지 추가 및 변경 사항이 있습니다.

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation{
    [image_signature setImage:[self resizeImage:image_signature.image]];
    return (toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft);
}
-(BOOL)shouldAutorotate {
    return YES;
}
- (NSUInteger)supportedInterfaceOrientations {
    [image_signature setImage:[self resizeImage:image_signature.image]];
    return UIInterfaceOrientationMaskLandscapeLeft;
}

주의 : IOS 5 에서 자동 회전을 강제 하려면 다음을 추가해야합니다.

- (void)viewDidLoad{
    [super viewDidLoad];
    if ([[[UIDevice currentDevice] systemVersion] floatValue] < 6.0)
        [[UIApplication sharedApplication] setStatusBarOrientation:UIDeviceOrientationLandscapeLeft animated:NO];    
}

마찬가지로,로드하는 컨트롤러에 관계없이 LANDSCAPE 컨트롤러를 종료 한 후 IOS 5에 대해 다시 자동 회전을 강제해야하지만 이제 UIDeviceOrientationPortraitPORTRAIT 컨트롤러로 이동하면서를 사용합니다.

- (void)viewDidLoad{
        [super viewDidLoad];
        if ([[[UIDevice currentDevice] systemVersion] floatValue] < 6.0)
            [[UIApplication sharedApplication] setStatusBarOrientation:UIDeviceOrientationPortrait animated:NO];    
    }

이제 마지막으로 (그리고 약간 이상합니다)-IOS에 따라 컨트롤러에서 다른 컨트롤러로 전환하는 방법을 변경해야합니다.

NSObject 클래스 "Schalter"(독일어에서 "Switch")를 만듭니다.

Schalter.h에서 다음과 같이 말합니다.

#import <Foundation/Foundation.h>

@interface Schalter : NSObject
+ (void)loadController:(UIViewController*)VControllerToLoad andRelease:(UIViewController*)VControllerToRelease;
@end

Schalter.m에서 다음과 같이 말합니다.

#import "Schalter.h"
#import "AppDelegate.h"

@implementation Schalter
+ (void)loadController:(UIViewController*)VControllerToLoad andRelease:(UIViewController*)VControllerToRelease{

    //adjust the frame of the new controller
    CGRect statusBarFrame = [[UIApplication sharedApplication] statusBarFrame];
    CGRect windowFrame = [[UIScreen mainScreen] bounds];
    CGRect firstViewFrame = CGRectMake(statusBarFrame.origin.x, statusBarFrame.size.height, windowFrame.size.width, windowFrame.size.height - statusBarFrame.size.height);
    VControllerToLoad.view.frame = firstViewFrame;

    //check version and go
    if (IOS_OLDER_THAN_6)
        [((AppDelegate*)[UIApplication sharedApplication].delegate).window addSubview:VControllerToLoad.view];
    else
        [((AppDelegate*)[UIApplication sharedApplication].delegate).window setRootViewController:VControllerToLoad];

    //kill the previous view controller
    [VControllerToRelease.view removeFromSuperview];
}
@end

이제 Schalter를 사용하는 방법은 다음과 같습니다 (Warehouse 컨트롤러에서 Products 컨트롤러로 이동한다고 가정).

#import "Warehouse.h"
#import "Products.h"

@implementation Warehouse
Products *instance_to_products;

- (void)goToProducts{
    instance_to_products = [[Products alloc] init];
    [Schalter loadController:instance_to_products andRelease:self];
}

bla-bla-bla your methods

@end

물론 instance_to_products개체 를 해제해야 합니다.

- (void)dealloc{
     [instance_to_products release];
     [super dealloc];
}

글쎄, 이거 다. 주저하지 말고 반대표를 던집니다. 상관 없어요. 이것은 평판이 아닌 솔루션을 찾는 사람들을위한 것입니다. 건배! 사바 마자 레.


작동합니다. iOS 6 이전 버전과 비슷하지만 다음과 UINavigationController같습니다.

UIViewController *portraitViewController = [[UIViewController alloc] init];
UINavigationController* nc = [[UINavigationController alloc] initWithRootViewController:portraitViewController];
[self.navigationController presentModalViewController:nc animated:NO];
[self.navigationController dismissModalViewControllerAnimated:NO];

나는 다음을 밀기 전에 이것을 부른다 UIViewController. UIViewController현재가 UIViewController가로 모드 인 경우에도 다음 푸시 된 항목이 세로 모드로 표시되도록 강제합니다 (세로에서 가로로도 작동해야 함). 나를 위해 iOS 4 + 5 + 6에서 작동합니다.


가장 좋은 해결책은 공식 사과 문서를 고수하는 것입니다. 그래서 나는 다음 방법을 사용하고 모든 것이 iOS 5 및 6에서 잘 작동합니다. 내 VC에서 다음 방법을 재정의합니다.

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // Return YES for supported orientations
    return UIInterfaceOrientationIsPortrait(interfaceOrientation);
}

iOS 6 용 메서드, 첫 번째 메서드는 지원되는 방향 마스크를 반환합니다 (이름에서 알 수 있음).

-(NSUInteger)supportedInterfaceOrientations{

    return UIInterfaceOrientationMaskPortrait;
}

두 번째는 VC가 표시 될 때 선호하는 인터페이스 방향을 VC에 알려줍니다.

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
    return UIInterfaceOrientationPortrait;
}

원하는 방향으로 세로를 변경하십시오.;)이 솔루션은 원활하게 작동합니다.이 간단한 솔루션을 다루는 매크로 및 기타 항목을 만드는 아이디어가 마음에 들지 않습니다. 이 도움을 바랍니다 ...


나는 동일한 문제가 있었다. 내 애플리케이션에서 27 개의 뷰가 세로로 26 개, 모든 방향에서 하나만 (이미지 뷰어 :)). 모든 클래스에 매크로를 추가하고 탐색을 대체하는 것은 제가 편한 해결책이 아니 었습니다.

그래서 나는 내 앱에 UINavigationController 메커니즘을 유지하고 이것을 다른 코드로 바꾸지 않고 싶었습니다.

해야 할 일 :

@ 1 didFinishLaunchingWithOptions 메소드의 애플리케이션 대리자

if ([[UIDevice currentDevice].systemVersion floatValue] < 6.0)
{
    // how the view was configured before IOS6
    [self.window addSubview: navigationController.view];
    [self.window makeKeyAndVisible];
}
else
{
    // this is the code that will start the interface to rotate once again
    [self.window setRootViewController: self.navigationController];
}

@ 2 navigationController가 자동 회전을 위해 YES로 응답하기 때문에 몇 가지 제한 사항을 추가해야합니다. UINavicationController-> YourNavigationController를 확장하고 인터페이스 빌더에 연결합니다.

@ 3 내비게이션 컨트롤러에서 "anoying new methods"를 재정의합니다.

이 클래스는이 응용 프로그램에 대해서만 사용자 지정되므로 컨트롤러에 대한 책임을지고 그 자리에서 응답 할 수 있습니다.

-(BOOL)shouldAutorotate {

    if ([self.viewControllers firstObject] == YourObject)
    {
         return YES;
    }
    return NO;
}
- (NSUInteger)supportedInterfaceOrientations {
     if ([self.viewControllers firstObject] == YourObject)
    {
         return UIINterfaceOrientationMaskLandscape;
    }
    return UIInterfaceOrientationMaskPortrait;
}

도움이 되길 바랍니다.


로부터 아이폰 OS 6 릴리스 노트 :

이제 iOS 컨테이너 (예 : UINavigationController)는 자동 회전 여부를 결정하기 위해 자식에게 문의하지 않습니다.

메시지를 계층 구조 아래로 VC 에게 rootViewController전달 합니까 ?shouldAutoRotateViewController


저는 OP pre-ios6 (모달 VC를 표시하고 해제)와 동일한 방법을 사용하여 가로 모드 (다른 모든 항목은 세로)로 단일 뷰 컨트롤러를 표시했습니다. 가로 VC가 세로로 표시된 ios6에서 중단되었습니다.

이 문제를 해결하기 위해 가로 VC에 preferredInterfaceOrientationForPresentation 메서드를 추가했습니다. 이제 os 5 및 os 6에서 잘 작동하는 것 같습니다.

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft);
}

- (BOOL)shouldAutorotate
{
return NO;
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{    
return UIInterfaceOrientationLandscapeLeft;
}

성공하지 못한 많은 다른 가능한 솔루션을 시도한 후 안녕하세요 다음 솔루션이 도움이되기를 바랍니다.

레시피를 준비했습니다. :).

문제 : iOS 6에서 navigationcontroller를 사용하여 viewcontroller의 방향을 변경해야합니다.

해결책:

탐색 제안

단계 1. 하나의 초기 UIviewcontroler는 그림과 같이 가로 및 세로 UInavigationControllers에 대한 모달 segues를 트리거합니다 ....

UIViewController1에서는 Appdelegate의 전역 변수에 따라 2 개의 segues 작업이 필요합니다 ....

-(void)viewDidAppear:(BOOL)animated{
    if([globalDelegate changeOrientation]==0){
        [self performSegueWithIdentifier:@"p" sender:self];
    }
    else{
        [self performSegueWithIdentifier:@"l" sender:self];
    }

}

또한 초상화로 돌아가는 방법이 필요합니다 & | 경치....

- (IBAction)dimis:(id)sender {
    [globalDelegate setChangeOrientation:0];
    [self dismissViewControllerAnimated:NO completion:nil];
}

2 단계. 각 NavigationController의 첫 번째 푸시 된 UiViewController는 함께 이동합니다.

-(NSUInteger)supportedInterfaceOrientations{
    return [self.navigationController supportedInterfaceOrientations];
}

-(BOOL)shouldAutorotate{
    return YES;
}

3 단계 . UInavigationController의 하위 클래스에서 supportedInterfaceOrientations 메서드를 덮어 씁니다 ....

customNavigationController에서 우리는 .....

-(NSUInteger)supportedInterfaceOrientations{
    if([self.visibleViewController isKindOfClass:[ViewController2 class]]){

        return UIInterfaceOrientationMaskPortrait;
    }
    else{
        return UIInterfaceOrientationMaskLandscape;

    }

}

4 단계. 스토리 보드 또는 코드에서 세로 및 가로 uinavigationcontroller 모두에 대해 wantsFullScreenLayout 플래그를 yes로 설정합니다.


Try segueing to a UINavigationController which uses a category or is subclassed to specify the desired orientation, then segue to the desired VC. Read more here.


As an alternative you can do the same using blocks:

UIViewController *viewController    = [[UIViewController alloc] init];
viewController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentViewController:viewController animated:NO completion:^{
    [self dismissViewControllerAnimated:NO completion:nil];
}];

Also, call it before pushing the new view.


Go to you Info.plist file and make the change 여기에 이미지 설명 입력


I had the same problem. If you want to force a particular view controller to appear in landscape, do it right before you push it into the navigation stack.

UIInterfaceOrientation currentOrientation = [[UIApplication sharedApplication] statusBarOrientation];
        if (currentOrientation == UIInterfaceOrientationPortrait ||
            currentOrientation == UIInterfaceOrientationPortraitUpsideDown)
            [[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeLeft];

        UIViewController *vc = [[UIViewController alloc] init];
        [self.navigationController pushViewController:vc animated:YES];
        [vc release];

I solved it by subclassing UINavigationController and overriding the supportedInterfaceOrientations of the navigation Controller as follow:

- (NSUInteger)supportedInterfaceOrientations
{
     return [[self topViewController] supportedInterfaceOrientations];
}

All the controllers implemented supportedInterfaceOrientations with their desired orientations.


다음 솔루션을 사용했습니다. 다른 모든 것과 다른 방향을 가진 하나의 뷰 컨트롤러에서 prepareForSegue 메서드 에 방향 검사를 추가했습니다 . 대상 뷰 컨트롤러가 현재 표시된 것과 다른 인터페이스 방향을 필요로하는 경우, 시퀀싱 중에 인터페이스가 회전하도록하는 메시지가 전송됩니다.

#import <objc/message.h>

...

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if(UIDeviceOrientationIsLandscape(self.interfaceOrientation))
    {
        UIInterfaceOrientation destinationOrientation;

        if ([[segue destinationViewController] isKindOfClass:[UINavigationController class]])
        {
            UINavigationController *navController = (UINavigationController *)[segue destinationViewController];
            destinationOrientation = [navController.topViewController preferredInterfaceOrientationForPresentation];
        } else
        {
            destinationOrientation = [[segue destinationViewController] preferredInterfaceOrientationForPresentation];
        }

        if ( destinationOrientation == UIInterfaceOrientationPortrait )
        {
            if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)])
            {
                objc_msgSend([UIDevice currentDevice], @selector(setOrientation:), UIInterfaceOrientationPortrait );
            }
        }
    }
}

참조 URL : https://stackoverflow.com/questions/12640870/ios-6-force-device-orientation-to-landscape

반응형