【问题标题】:Forced orientation change does not work sometimes强制改变方向有时不起作用
【发布时间】:2016-06-18 02:37:19
【问题描述】:

当在我的应用程序中按下某个按钮时,视图应将方向从纵向更改为 景观。当用户回来时,视图控制器应该变回纵向。但 有时方向不会改变或使用了错误的视图框架。

这是我的代码

-(void)btnSignClicked:(CustomSignButton *)btn {
    isSignButtonClicked = true;
    if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_7_0) {
        NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeRight];
        [[UIDevice currentDevice] setValue:value forKey:@"orientation"];
    }
    else
    {
        [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight animated:YES];
    }
    selectedWaiverId = btn.customTag;

    SignatureView *obj = [[SignatureView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height) delegate:self]; // Most of time got size (568,320) but some time i got (320,568), Don't know why
    [self.view addSubview:obj];
}

#pragma mark - SIGNATUREVIEW DELEGATE
-(void)removeSignatureView:(SignatureView *)signatureView {
    isSignButtonClicked = false;

    if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_7_0)
    {
        NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
        [[UIDevice currentDevice] setValue:value forKey:@"orientation"]; // Some time not changed the orientation are view remaining in landscape 
    }
    else
    {
        [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:YES];
    }

    [signatureView removeFromSuperview];
    signatureView = nil;

}
#pragma mark
#pragma mark - Rotate screen
-(UIInterfaceOrientationMask)supportedInterfaceOrientations
{
    if (isSignButtonClicked == true)
    {
        return UIInterfaceOrientationMaskLandscapeRight|UIInterfaceOrientationMaskLandscape;
    }
    else
    {
        return UIInterfaceOrientationMaskPortrait;
    }
}
- (BOOL)shouldAutorotate
{
    return YES;
}
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    if (isSignButtonClicked == true)
    {
        return (interfaceOrientation == UIInterfaceOrientationLandscapeRight);
    }
    else
    {
        return (interfaceOrientation == UIInterfaceOrientationPortrait);
    }

}

更新

有时viewWillTransitionToSize方法没有被调用所以我也整合了这个通知

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

但有时这也行不通。

【问题讨论】:

  • 这种改变方向的方法是否已记录在案,还是一种黑客行为?
  • 相当肯定的“可信和/或官方消息来源”会建议不要这样做。
  • 它在文档@Sulthan 中。

标签: ios objective-c ios8 uiinterfaceorientation


【解决方案1】:

请参阅此link,特别是,我认为您应该检查视图控制器的条件,它们是否符合 Apple 的建议

例如检查最顶层全屏视图控制器的supportedInterfaceOrientations方法

【讨论】:

    【解决方案2】:

    尝试在此块中添加所有旋转更改代码

    dispatch_async(dispatch_get_main_queue(), 
    {
         //changing orientation code + isSignButtonClicked = true (or false) 
    });
    

    您不必使用shouldAutorotateshouldAutorotateToInterfaceOrientation

    至于出现错误的视图框架,即使您正在以编程方式创建视图,您也需要为您在此 viewController 中使用的每个视图使用自动布局约束

    【讨论】:

    • 这是非常古老的代码,所以自动布局没有在其中实现。我已经在代码中使用了 dispatch 但没有成功。
    • 我也有旧代码,但 id 必须将其更改为自动布局才能正确获取帧。这不是很痛苦。您可以在代码中设置框架的位置以编程方式自动布局。您还需要将 info.plist 中的 ViewControllerBasedOrientation 添加为 YES
    • info.plist 中没有“ViewControllerBasedOrientation”选项
    【解决方案3】:

    添加 AppDelegate.m 文件或任何基本控制器文件

     @implementation UINavigationController (Orientation)
    
    
    - (UIInterfaceOrientationMask) supportedInterfaceOrientations
    {
    
        return [(UIViewController*)[[self viewControllers] lastObject] supportedInterfaceOrientations];
    
    }
    - (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
    {
        return [(UIViewController*)[[self viewControllers] lastObject] preferredInterfaceOrientationForPresentation];
    }
    
    - (BOOL) shouldAutorotate
    {
        return [(UIViewController*)[[self viewControllers] lastObject] shouldAutorotate];
    }
    
    @end
    

    现在将您的 ViewController 对象放入 UINavigationController 对象并推送视图控制器。

    EX.

    UINavigationController *obj=[[UINavigationController  alloc] initWithRootViewController:_yourViewCtrlObj];
    
    [self presentViewController:obj.....]; 
    
    or
    [self.navigationController pushViewController:obj animated:YES];
    

    在所有视图控制器中设置您想要的方向。

    【讨论】:

    • 我已经完成了所有这些,除了现在并关闭了 VC,因为我没有使用新的 VC,我只展示了视图
    【解决方案4】:

    如果您的应用使用 UINavigationViewController 则为 UINAvigationController 创建一个自定义类,例如:

    //CustomNavViewController.h

    #import <UIKit/UIKit.h>
    @interface CustomNavViewController : UINavigationController <UINavigationControllerDelegate>
    
    @end
    

    //CustomNavViewController.m

    #import "CustomNavViewController.h"
    @interface CustomNavViewController ()
    @end
    
    @implementation CustomNavViewController
    - (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    }
    - (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
    }
    - (BOOL)shouldAutorotate {
    return [self.visibleViewController shouldAutorotate];
    }
    
    - (UIInterfaceOrientationMask)supportedInterfaceOrientations {
    return [self.visibleViewController supportedInterfaceOrientations];
    }
    @end
    

    现在在您的 AppDelegate 中声明一个属性,例如:

    //AppDelegate.h

     @property (assign, nonatomic) BOOL shouldRotate;
    

    //AppDelegate.m

    - (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
    {
    if (self.shouldRotate) {
        return  UIInterfaceOrientationMaskLandscapeLeft|UIInterfaceOrientationMaskLandscapeRight;
    }
    return UIInterfaceOrientationMaskPortrait;
    }
    

    现在你可以调用需要固定方向的 ViewController 的方向方法,例如:

    //YourViewController.m

    -(BOOL)shouldAutorotate{
    return NO;
    }
    
    - (UIInterfaceOrientationMask)supportedInterfaceOrientations{
         return UIInterfaceOrientationMaskLandscape;
    }
    
    - (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
    return UIInterfaceOrientationLandscapeLeft;
    }
    

    现在这里是将 AppDelegate shouldRotate 属性设置为 true 和 false 以获得所需方向的技巧

    如果您使用 ViewController 的默认演示,那么

    AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
    [appDelegate setShouldRotate:true];// Remember first update the value then present the ViewController
    [self presentViewController:yourViewController animated:YES completion:nil];
    

    和你解散时一样

     AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
    [appDelegate setShouldRotate:false];
    [self dismissViewControllerAnimated:YES completion:nil];
    

    如果您使用的是故事板,则直接在 Identity Inspector 自定义类部分添加 CustomNavViewController

    然后按照上述步骤操作。希望它有效

    【讨论】:

    • 我已经完成了所有这些,除了现在并关闭了 VC,因为我没有使用新的 VC,我只展示了视图
    【解决方案5】:

    当你说“当用户回来时,视图控制器应该变回纵向”,你的意思是用户正在点击导航控制器上的后退按钮吗?如果是这样,我之前看到过这个问题,并在另一个 SO 帖子中发布了一个对我有用的解决方案:A: Locking device orientation on a view fails when going back in NavBar。我记得过渡很艰难,但它奏效了。

    不久前,我还写了一个blog post,讨论了与视图控制器方向锁定有关的其他一些情况。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多