IT story

iPhone 방향을 설정하는 문서화 된 방법이 있습니까?

hot-time 2020. 8. 28. 07:59
반응형

iPhone 방향을 설정하는 문서화 된 방법이 있습니까?


특정보기에서 장치 회전을 지원하고 싶지만 다른보기는 가로 모드에서 특히 의미가없는 앱이 있으므로보기를 교체 할 때 강제로 회전을 세로로 설정하고 싶습니다.

트릭을 수행하지만 분명히 컴파일러 경고를 생성하고 SDK의 향후 개정판에서 사라질 수있는 문서화되지 않은 속성 설정자가 UIDevice에 있습니다.

[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationPortrait];

방향을 강제하는 문서화 된 방법이 있습니까?

업데이트 : 나는 이미 구현했기 때문에 shouldAutorotateToInterfaceOrientation을 찾고 있지 않기 때문에 예제를 제공 할 것이라고 생각했습니다.

내 앱이 View 1에서 가로 및 세로를 지원하고 View 2에서는 세로 만 지원하고 싶습니다. 모든보기에 대해 shouldAutorotateToInterfaceOrientation을 이미 구현했지만 사용자가 View 1에서 가로 모드에있는 경우 View 2로 전환하면 다시 세로로 회전합니다.


이것은 최신 iPhone 3.1.2 SDK에서 더 이상 문제가되지 않습니다. 이제 스택으로 다시 푸시되는 뷰의 요청 된 방향을 따르는 것으로 보입니다. 이는 이전 iPhone OS 버전을 감지하고 최신 릴리스 이전 인 경우에만 setOrientation을 적용해야 함을 의미합니다.

Apple의 정적 분석이 이전 SDK 제한 사항을 해결하고 있음을 이해하는지 여부는 명확하지 않습니다. 개인적으로 Apple은 다음 업데이트에서 메서드 호출을 제거하라는 지시를 받았으므로 이전 장치에 대한 해킹이 승인 프로세스를 통과할지 아직 확실하지 않습니다.


이것은 사실이 있은 지 오래되었지만 탐색 컨트롤러를 사용하지 않거나 문서화되지 않은 방법을 사용하고 싶지 않은 사람이 올 경우를 대비하여 :

UIViewController *c = [[UIViewController alloc]init];
[self presentModalViewController:c animated:NO];
[self dismissModalViewControllerAnimated:NO];
[c release];

바닐라 뷰 컨트롤러를 표시하고 해제하는 것으로 충분합니다.

분명히 shouldAutorotateToInterfaceOrientation 재정의에서 방향을 확인하거나 거부해야합니다. 그러나 이로 인해 시스템에서 shouldAutorotate ...를 다시 호출합니다.


세로에서 가로로 강제로 회전 시키려면 여기에 코드가 있습니다. 뷰의 중심을 조정해야합니다. 내 것이 올바른 위치에 뷰를 배치하지 않았다는 것을 알았습니다. 그렇지 않으면 완벽하게 작동했습니다. 팁 고마워.

if(UIInterfaceOrientationIsLandscape(self.interfaceOrientation)){

        [UIView beginAnimations:@"View Flip" context:nil];
        [UIView setAnimationDuration:0.5f];
        [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];

        self.view.transform = CGAffineTransformIdentity;
        self.view.transform = CGAffineTransformMakeRotation(degreesToRadian(90));
        self.view.bounds = CGRectMake(0.0f, 0.0f, 480.0f, 320.0f);
        self.view.center = CGPointMake(160.0f, 240.0f);

        [UIView commitAnimations];
}

내가 알 수 있듯이 setOrientation:방법이 작동하지 않거나 더 이상 작동하지 않습니다. 이 작업을 수행하기 위해 수행하는 작업은 다음과 같습니다.

먼저 #imports 바로 아래의 파일 맨 위에이 정의를 넣으십시오.

#define degreesToRadian(x) (M_PI * (x) / 180.0)

그런 다음 viewWillAppear:방법에서

[[UIApplication sharedApplication] setStatusBarHidden:YES animated:NO];     
if (self.interfaceOrientation == UIInterfaceOrientationPortrait) {  
    self.view.transform = CGAffineTransformIdentity;
    self.view.transform = CGAffineTransformMakeRotation(degreesToRadian(90));
    self.view.bounds = CGRectMake(0.0, 0.0, 480, 320);
}

애니메이션을 원하면 다음과 같이 애니메이션 블록에 전체를 래핑 할 수 있습니다.

[UIView beginAnimations:@"View Flip" context:nil];
[UIView setAnimationDuration:1.25];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];

[[UIApplication sharedApplication] setStatusBarHidden:YES animated:NO];     
if (self.interfaceOrientation == UIInterfaceOrientationPortrait) {  
    self.view.transform = CGAffineTransformIdentity;
    self.view.transform = CGAffineTransformMakeRotation(degreesToRadian(90));
    self.view.bounds = CGRectMake(0.0, 0.0, 480, 320);
}
[UIView commitAnimations];

그런 다음 세로 모드 컨트롤러에서 반대로 할 수 있습니다. 현재 가로 모드인지 확인하고, 그렇다면 다시 세로 모드로 회전합니다.


UIViewController화면 UINavigationController에 가로 방향으로 표시 되는 문제가 발생했습니다 . 그러나 다음 뷰 컨트롤러가 흐름에서 밀려 나면 장치가 세로 방향으로 돌아 가야했습니다.

내가 주목 shouldAutorotateToInterfaceOrientation:한 것은 새 뷰 컨트롤러가 스택에 푸시 될 때 메서드가 호출되지 않고 뷰 컨트롤러가 스택에서 팝될 때 호출된다는 것입니다 .

이를 활용하여 내 앱 중 하나에서이 코드 스 니펫을 사용하고 있습니다.

- (void)selectHostingAtIndex:(int)hostingIndex {

    self.transitioning = YES;

    UIViewController *garbageController = [[[UIViewController alloc] init] autorelease];
    [self.navigationController pushViewController:garbageController animated:NO];
    [self.navigationController popViewControllerAnimated:NO];

    BBHostingController *hostingController = [[BBHostingController alloc] init];
    hostingController.hosting = [self.hostings objectAtIndex:hostingIndex];
    [self.navigationController pushViewController:hostingController animated:YES];
    [hostingController release];

    self.transitioning = NO;
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
    if (self.transitioning)
        return (toInterfaceOrientation == UIInterfaceOrientationPortrait);
    else
        return YES;
}

기본적으로 빈 뷰 컨트롤러를 만들고 스택에 밀어 넣은 다음 즉시 튀어 나옴으로써 인터페이스를 세로 위치로 되돌릴 수 있습니다. 컨트롤러가 튀어 나오면 처음부터 밀려 고했던 컨트롤러를 누르기 만하면됩니다. 시각적으로보기 좋습니다. 비어있는 임의의 뷰 컨트롤러는 사용자가 볼 수 없습니다.


kdbdallas , Josh 가 이미 제공 한 답변 중 두 가지를 사용하여 프로그래밍 방식으로 iPhone을 필요한 방향으로 강제하는 간단한 방법이 있습니다 .

//will rotate status bar
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight];


//will re-rotate view according to statusbar
UIViewController *c = [[UIViewController alloc]init];
[self presentModalViewController:c animated:NO];
[self dismissModalViewControllerAnimated:NO];
[c release];

매력처럼 작동 :)

편집하다:

iOS 6의 경우이 기능을 추가해야합니다. (모달 뷰 컨트롤러에서 작동)

- (NSUInteger)supportedInterfaceOrientations
{
    return (UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight);
}

나는 이것에 대한 좋은 해결책을 찾기 위해 파고 파고있었습니다. 트릭을 수행하는이 블로그 게시물을 찾았습니다. 키에서 가장 바깥 쪽 뷰를 제거 UIWindow하고 다시 추가하면 시스템이 shouldAutorotateToInterfaceOrientation:컨트롤러 에서 메서드 를 다시 쿼리 하여 올바른 방향이 적용되도록 강제합니다. 그것을보십시오 : 아이폰은 uiview가 방향을 바꾸도록 강제 합니다.


Josh의 대답이 잘 작동합니다.

그러나 "방향이 변경되었습니다 . UI를 업데이트하십시오" 알림을 게시하는 것을 선호합니다 . 이 알림이 뷰 컨트롤러에 수신되면를 호출 shouldAutorotateToInterfaceOrientation:하여 원하는 방향으로 돌아가서 방향을 설정할 수 있습니다 YES.

[[NSNotificationCenter defaultCenter] postNotificationName:UIDeviceOrientationDidChangeNotification object:nil];

유일한 문제는 애니메이션 없이 방향 다시 지정해야한다는 것 입니다. 당신은 사이에이 줄을 마무리해야 beginAnimations:하고 commitAnimations원활한 전환을 달성 할 수 있습니다.

도움이 되었기를 바랍니다.


FWIW, 여기에 수동으로 방향을 설정하는 구현이 있습니다 (앱의 루트 뷰 컨트롤러, natch로 이동).

-(void)rotateInterfaceToOrientation:(UIDeviceOrientation)orientation{

    CGRect bounds = [[ UIScreen mainScreen ] bounds ];
    CGAffineTransform t;
    CGFloat r = 0;
    switch ( orientation ) {
        case UIDeviceOrientationLandscapeRight:
            r = -(M_PI / 2);
            break;
        case UIDeviceOrientationLandscapeLeft:
            r  = M_PI / 2;
            break;
    }
    if( r != 0 ){
        CGSize sz = bounds.size;
        bounds.size.width = sz.height;
        bounds.size.height = sz.width;
    }
    t = CGAffineTransformMakeRotation( r );

    UIApplication *application = [ UIApplication sharedApplication ];

    [ UIView beginAnimations:@"InterfaceOrientation" context: nil ];
    [ UIView setAnimationDuration: [ application statusBarOrientationAnimationDuration ] ];
    self.view.transform = t;
    self.view.bounds = bounds;
    [ UIView commitAnimations ];

    [ application setStatusBarOrientation: orientation animated: YES ];     
}

다음 UINavigationControllerDelegate방법 과 결합됩니다 (를 사용한다고 가정 UINavigationController).

-(void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated{
    // rotate interface, if we need to
    UIDeviceOrientation orientation = [[ UIDevice currentDevice ] orientation ];
    BOOL bViewControllerDoesSupportCurrentOrientation = [ viewController shouldAutorotateToInterfaceOrientation: orientation ];
    if( !bViewControllerDoesSupportCurrentOrientation ){
        [ self rotateInterfaceToOrientation: UIDeviceOrientationPortrait ];
    }
}

수신 UIViewController이 현재 장치 방향을 지원 하는지 여부에 따라 루트 뷰를 회전합니다 . 마지막으로 rotateInterfaceToOrientation표준 iOS 기능을 모방하기 위해 실제 장치 방향 변경에 연결하는 것이 좋습니다. 이 이벤트 핸들러를 동일한 루트 뷰 컨트롤러에 추가합니다.

-(void)onUIDeviceOrientationDidChangeNotification:(NSNotification*)notification{
    UIViewController *tvc = self.rootNavigationController.topViewController;
    UIDeviceOrientation orientation = [[ UIDevice currentDevice ] orientation ];
    // only switch if we need to (seem to get multiple notifications on device)
    if( orientation != [[ UIApplication sharedApplication ] statusBarOrientation ] ){
        if( [ tvc shouldAutorotateToInterfaceOrientation: orientation ] ){
            [ self rotateInterfaceToOrientation: orientation ];
        }
    }
}

Finally, register for UIDeviceOrientationDidChangeNotification notifications in init or loadview like so:

[[ NSNotificationCenter defaultCenter ] addObserver: self
                                           selector: @selector(onUIDeviceOrientationDidChangeNotification:)
                                               name: UIDeviceOrientationDidChangeNotification
                                             object: nil ];
[[ UIDevice currentDevice ] beginGeneratingDeviceOrientationNotifications ];

This works for me (thank you Henry Cooke):

The aim for me was to deal with landscape orientations changes only.

init method:

[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(orientationChanged:)
                                             name:UIDeviceOrientationDidChangeNotification
                                           object:nil];

- (void)orientationChanged:(NSNotification *)notification {    
    //[[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];
    UIDeviceOrientation orientation = [UIDevice currentDevice].orientation;
    CGRect bounds = [[ UIScreen mainScreen ] bounds ];
    CGAffineTransform t;
    CGFloat r = 0;
    switch ( orientation ) {
        case UIDeviceOrientationLandscapeRight:
            r = 0;
            NSLog(@"Right");
            break;
        case UIDeviceOrientationLandscapeLeft:
            r  = M_PI;
            NSLog(@"Left");
            break;
        default:return;
    }

    t = CGAffineTransformMakeRotation( r );

    UIApplication *application = [ UIApplication sharedApplication ];
    [ UIView beginAnimations:@"InterfaceOrientation" context: nil ];
    [ UIView setAnimationDuration: [ application statusBarOrientationAnimationDuration ] ];
    self.view.transform = t;
    self.view.bounds = bounds;
    [ UIView commitAnimations ];

    [ application setStatusBarOrientation: orientation animated: YES ];
}

I have an app where I would like to support device rotation in certain views but other don't particularly make sense in Landscape mode, so as I swapping the views out I would like to force the rotation to be set to portrait.

I realise that the above original post in this thread is very old now, but I had a similar problem to it - ie. all of the screens in my App are portrait only, with the exception of one screen, which can be rotated between landscape and portrait by the user.

This was straightforward enough, but like other posts, I wanted the App to automatically return to portrait regardless of the current device orientation, when returning to the previous screen.

The solution I implemented was to hide the Navigation Bar while in landscape mode, meaning that the user can only return to previous screens whilst in portrait. Therefore, all other screens can only be in portrait.

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)pInterfaceOrientation {
    BOOL lHideNavBar = self.interfaceOrientation == UIInterfaceOrientationPortrait ? NO : YES;
    [self.navigationController setNavigationBarHidden:lHideNavBar animated:YES];
}

This also has the added benefit for my App in that there is more screen space available in landscape mode. This is useful because the screen in question is used to display PDF files.

Hope this helps.


I solved this quite easily in the end. I tried every suggestion above and still came up short, so this was my solution:

In the ViewController that needs to remain Landscape (Left or Right), I listen for orientation changes:

    [[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(didRotate:)
                                             name:UIDeviceOrientationDidChangeNotification object:nil];

Then in didRotate:

- (void) didRotate:(NSNotification *)notification
{   if (orientationa == UIDeviceOrientationPortrait) 
    {
        if (hasRotated == NO) 
        {
            NSLog(@"Rotating to portait");
            hasRotated = YES;
            [UIView beginAnimations: @"" context:nil];
            [UIView setAnimationDuration: 0];
            self.view.transform = CGAffineTransformIdentity;
            self.view.transform = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(-90));
            self.view.bounds = CGRectMake(0.0f, 0.0f, 480.0f, 320.0f);
            self.view.frame = CGRectMake(0.0f, 0.0f, 480.0f, 320.0f);
            [UIView commitAnimations];

    }
}
else if (UIDeviceOrientationIsLandscape( orientationa))
{
    if (hasRotated) 
    {
        NSLog(@"Rotating to lands");
        hasRotated = NO;
        [UIView beginAnimations: @"" context:nil];
        [UIView setAnimationDuration: 0];
        self.view.transform = CGAffineTransformIdentity;
        self.view.transform = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(0));
        self.view.bounds = CGRectMake(0.0f, 0.0f, 320.0f, 480.0f);
        self.view.frame = CGRectMake(0.0f, 0.0f, 320.0f, 480.0f);
        [UIView commitAnimations];

    }
}

Keep in mind any Super Views/Subviews that use autoresizing, as the view.bounds/frame are being reset explicitly...

The only caveat to this method for keeping the view Landscape, is the inherent animation switching between orientations that has to occur, when it would be better to have it appear to have no change.


iOS 6 solution:

[[[self window] rootViewController] presentViewController:[[UIViewController alloc] init] animated:NO completion:^{
    [[[self window] rootViewController] dismissViewControllerAnimated:NO completion:nil];
}];

The exact code depends per app and also where you place it (I used it in my AppDelegate). Replace [[self window] rootViewController] with what you use. I was using a UITabBarController.


I found a solution and wrote something in french (but code are in english). here

The way is to add the controller to the window view (the controller must possess a good implementation of the shouldRotate.... function).


If you are using UIViewControllers, there is this method:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation

Return NO for the view controllers containing the views you don't want to rotate.

More info here


I don't think this is possible to do at run-time, though you could of course just apply a 90 degree transform to your UI.


This is what I use. (You get some compile warnings but it works in both the Simulator and the iPhone)

[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight];
[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeRight];

참고URL : https://stackoverflow.com/questions/181780/is-there-a-documented-way-to-set-the-iphone-orientation

반응형