V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
iOS 开发实用技术导航
NSHipster 中文版
http://nshipster.cn/
cocos2d 开源 2D 游戏引擎
http://www.cocos2d-iphone.org/
CocoaPods
http://cocoapods.org/
Google Analytics for Mobile 统计解决方案
http://code.google.com/mobile/analytics/
WWDC
https://developer.apple.com/wwdc/
Design Guides and Resources
https://developer.apple.com/design/
Transcripts of WWDC sessions
http://asciiwwdc.com
Cocoa with Love
http://cocoawithlove.com/
Cocoa Dev Central
http://cocoadevcentral.com/
NSHipster
http://nshipster.com/
Style Guides
Google Objective-C Style Guide
NYTimes Objective-C Style Guide
Useful Tools and Services
Charles Web Debugging Proxy
Smore
parkman
V2EX  ›  iDev

[求教][IOS orientation] IOS-7如何固定单个viewController的方向?

  •  
  •   parkman · 2014-01-19 10:56:37 +08:00 · 17249 次点击
    这是一个创建于 3968 天前的主题,其中的信息可能已经有所发展或是发生改变。
    app需要支持两个屏幕方向,其中一些controller是固定竖屏,一些是固定横屏,我试了下stackoverflow中的这种方法,
    http://stackoverflow.com/questions/12520030/how-to-force-a-uiviewcontroller-to-portait-orientation-in-ios-6

    我写了一个sample code 在GitHub上 https://github.com/cseparkman/onlyTest:
    分别设置第一个VC(View Controller)仅仅支持LandscapeRight,第二个VC支持Portrait.

    问题在于:
    1. 第一个VC(View Controller) LandscapeRight。 [没问题]
    2. 紧接着点击button进入第二个VC 还是LandscapeRight [有问题] ,然后你尝试着晃动手机。第二个VC 将成为 Portrait。
    3. 再紧接着点击返回时, 第一个又是 LandscapeRight


    请问大家知不知道如何解决这个问题?
    27 条回复    1970-01-01 08:00:00 +08:00
    Kai
        1
    Kai  
    MOD
       2014-01-19 11:07:22 +08:00
    第二个 VC 内,viewWillAppear: 内可以使用 [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait]
    txx
        2
    txx  
       2014-01-19 11:09:34 +08:00
    在 nav 那里下断点 你会发现 进了二级之后 没有触发 shouldAutorotate
    Kai
        3
    Kai  
    MOD
       2014-01-19 11:13:36 +08:00
    parkman
        4
    parkman  
    OP
       2014-01-19 11:23:53 +08:00
    @txx 这个我发现了
    txx
        5
    txx  
       2014-01-19 11:27:09 +08:00
    @parkman 黑科技:
    objc_msgSend([UIDevice currentDevice], @selector(setOrientation:), UIInterfaceOrientationPortrait); 写在 第二个页面里面 viewWillAppear 里面。。。。

    然后加入#import <objc/message.h>

    原来iOS5 的API iOS6 消失了= =
    bytelee
        6
    bytelee  
       2014-01-19 11:28:52 +08:00
    直接贴给你方法看看吧:
    - (void)setOristation:(UIDeviceOrientation)oritation
    {
    if (oritation != [[UIDevice currentDevice] orientation] && [[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)])
    {
    SEL selector = NSSelectorFromString(@"setOrientation:");
    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[UIDevice instanceMethodSignatureForSelector:selector]];
    [invocation setSelector:selector];
    [invocation setTarget:[UIDevice currentDevice]];
    int val = oritation;
    [invocation setArgument:&val atIndex:2];
    [invocation invoke];

    CGRect bounds = [[UIScreen mainScreen] bounds];

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.3];
    [UIView setAnimationCurve:2];
    CGRect frame = CGRectZero;
    if(oritation == UIDeviceOrientationLandscapeLeft)
    {
    frame = CGRectMake(bounds.size.width-20, 0, 20, bounds.size.height);
    }
    else if(oritation == UIDeviceOrientationLandscapeRight)
    {
    frame = CGRectMake(0, 0, 20, bounds.size.height);
    }
    else if(oritation == UIDeviceOrientationPortraitUpsideDown)
    {
    frame = CGRectMake(0, bounds.size.height-20, bounds.size.width, 20);
    }
    else if(oritation == UIDeviceOrientationPortrait)
    {
    frame = CGRectMake(0, 0, bounds.size.width, 20);
    }
    self.statusBarView.frame = frame;
    [UIView commitAnimations];
    }
    [UIViewController attemptRotationToDeviceOrientation];
    }
    parkman
        7
    parkman  
    OP
       2014-01-19 11:31:57 +08:00
    @txx
    iOS5 的API iOS6 消失了= = 这个蛮难
    你的例子有sample 吗
    parkman
        8
    parkman  
    OP
       2014-01-19 11:32:15 +08:00
    @Kai 不work 啊
    txx
        9
    txx  
       2014-01-19 11:56:05 +08:00
    txx
        10
    txx  
       2014-01-19 12:00:49 +08:00   ❤️ 1
    @parkman objc_msgSend([UIDevice currentDevice], @selector(setOrientation:), UIInterfaceOrientationPortrait); 这么写有问题,最后一个忘了加括号...

    objc_msgSend([UIDevice currentDevice], @selector(setOrientation:), @(UIInterfaceOrientationPortrait));

    否则永远都是portrait
    qdvictory
        11
    qdvictory  
       2014-01-19 12:49:01 +08:00 via iPhone
    dorentus
        12
    dorentus  
       2014-01-19 13:43:53 +08:00
    只 iOS 7 的话,ViewController 子类覆盖下面两个方法就 OK 了吧:

    - (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation;
    - (NSUInteger)supportedInterfaceOrientations;

    ref: https://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/RespondingtoDeviceOrientationChanges/RespondingtoDeviceOrientationChanges.html
    parkman
        13
    parkman  
    OP
       2014-01-19 15:41:56 +08:00
    @qdvictory 当pop的时候,也就是3,无法触发方法 shouldAutorotate
    parkman
        14
    parkman  
    OP
       2014-01-19 15:42:39 +08:00
    @dorentus 你看看我的GitHub code 就是 覆盖了方法
    parkman
        16
    parkman  
    OP
       2014-01-19 15:57:15 +08:00
    @qdvictory
    我把你的code放进来 运行还是有问题
    PrideChung
        17
    PrideChung  
       2014-01-19 16:15:44 +08:00
    - shouldAutorotate 和 - supportedInterfaceOrientations 只有设备改变方向的时候才会被调用,光覆写着两个方法是不行的。
    parkman
        18
    parkman  
    OP
       2014-01-19 17:02:20 +08:00
    @PrideChung 还有什么做法吗?

    txx我的sample code加了一段强制rotation的代码
    qdvictory
        19
    qdvictory  
       2014-01-19 17:42:37 +08:00 via iPhone
    @parkman pop出来你要旋转的还是nav bar,而不是你push出来的,你得明白了vc之间的逻辑关系才好对症下药
    ZircoN
        20
    ZircoN  
       2014-01-19 18:25:37 +08:00
    我看到你头像进来的。
    parkman
        21
    parkman  
    OP
       2014-01-19 18:26:40 +08:00
    @qdvictory 能丢个code 出来看看吗? 我不是很理解你的意思
    txx
        22
    txx  
       2014-01-19 18:34:54 +08:00 via iPhone
    @parkman 为什么还没截贴呢 就因为我用了私有api么?
    parkman
        23
    parkman  
    OP
       2014-01-19 19:18:39 +08:00
    @txx 没有 就是其他人也有说了一些方法,我试了不可行。 就问问什么原理
    icyalala
        24
    icyalala  
       2014-01-19 22:46:40 +08:00
    在你的NavigationController里面加几句话:

    - (void)viewDidLoad
    {
    [super viewDidLoad];
    self.delegate = self;
    }


    - (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
    UIViewController *vc = [[UIViewController alloc] init];
    [self presentViewController:vc animated:NO completion:NULL];
    [vc dismissViewControllerAnimated:NO completion:NULL];
    }

    详情见http://stackoverflow.com/questions/15519486/presenting-navigation-controller-in-landscape-mode-is-not-working-ios-6-0

    主要是,你一直是在push和pop,rootViewController始终NavigationController。不旋转设备,不会引起auto rotate动作,只能用一些其他奇葩的方法了。

    你要用presentViewController,改变了rootViewController,就不会有这些问题了。
    ldehai
        25
    ldehai  
       2014-01-19 23:12:48 +08:00
    在CRPortaint类中加上这个来触发方向更新
    - (void)viewWillAppear:(BOOL)animated
    {
    [self presentViewController:[UIViewController new] animated:NO completion:^{ [self dismissViewControllerAnimated:NO completion:nil]; }];
    }
    ldehai
        26
    ldehai  
       2014-01-20 07:28:36 +08:00
    @parkman 其实这种交互设计不符合苹果的要求。具体到你这个例子,第一个viewController应该所有方向都支持,然后第二个可以固定一个方向。从第二个返回时,方向保持不变。
    parkman
        27
    parkman  
    OP
       2014-01-20 08:29:12 +08:00
    @ldehai @cyalala

    I see。
    必须是modal 出来的 view 才可以变换设备方向。
    navigation controller Pop Push的view 是 苹果设计HIG的原则。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2696 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 12:09 · PVG 20:09 · LAX 04:09 · JFK 07:09
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.