旧工程适配ios6和iphone5 之 适配ios6转屏

今天Boss跟我说,要我准备去适配ios6,于是我去鸟哥的博客看了下,然后有请教了别人,但是没达到效果,一直不知道问题在哪,后来看文档,google才发现问题关键所在。现在大致说下:

     

在ios6.0中shouldAutorotateToInterfaceOrientation:不再起作用了,ios使用shouldAutorotate和supportedInterfaceOrientations来控制旋转效果。
 
 
我试了几次,发现ios6.0真正起作用的旋转有三种:
1.在info.plist这里设置来控制,还可以在appDelegate的这个函数里面设置

- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window,在这个里面设置了,那么info.plist里面设置的就会失效;

2.直接把视图加在window上,(如:[self.window addSubview:vc.view])这种方法可以脱离info.plist的控制,

shouldAutorotate和supportedInterfaceOrientations来控制方向;
 
3.使用rootViewController(如:self.window.rootViewController = rootVC) , 添加shouldAutorotate方法,但是受info.plist的限制。

相信大多数人都是使用的第三种,但是这个要特别注意:当window的rootViewController设置为UINavigationController的时候,你需要自定义UINavigationController,因为你需要在这里面,写shouldAutorotate和supportedInterfaceOrientations方法。如果你不这样做,那么如果你有的界面需要转屏的话,可能会有问题。
上面的这些方法都限制于顶层视图控制,这也是ios6与之前的ios版本不同的地方,如果要想在子视图中添加旋转效果,则需要在顶层视图中开启shouldAutorotate方法,在子视图控制器中就可以使用supportedInterfaceOrientations方法。
一些示例代码:
首先
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
    // Override point for customization after application launch.
    RootViewController  *vc   = [[RootViewController alloc] init];
    self.window.rootViewController = vc;
    [vc release];
    [self.window makeKeyAndVisible];
    
//  直接添加视图来控制
//  RootViewController *vc = [[RootViewController alloc] init];    
//  [self.window addSubview:vc.view];
    return YES;
}


然后在顶层视图上开启旋转和控制
//在RootViewController中开启旋转
- (BOOL)shouldAutorotate
{
    return YES;
}

-(NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskLandscape;
}


最后在子视图控制器中直接使用
//- (BOOL)shouldAutorotate
//{
//    return YES;
//}

//在FirstViewController中直接使用
-(NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;
}


总结:
 在ios4 and 5 , 都是由具体的ViewController来决定对应的view的orientation设置,但是在ios6,则是由top-most controller,即顶层视图控制器来决定view的orientation设置。
 

在iOS 4 and 5,都是由具体的view controller来决定对应的view的orientation设置。而在iOS 6,则是由top-most  controller来决定view的orientation设置。

就像我们刚才说的那个:如果你的app的window的rootViewController是UINavigationController的nav,那么在nav里的stack依次是:main view ->sub view ->sub sub view, 并且在main view里面可以进入下一个视图model view,是present进去的, 那么在ios4 and 5 ,如果你要这些view只支持横屏orientation,那么你只需要在main view, sub view ,sub sub view ,model view的控制器里面,添加这个函数即可:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return UIInterfaceOrientationIsLandscape(orientation);
}


但是对于ios6来说,由于是top-most controller来设置方向的,因此如果你单独的在main view ,sub view,sub sub view里面添加下面的代码是没有任何效果的,而应该是在navigationController里添加下列代码,这也是因为我先为什么说,需要你自定义navigationController的原因。而modal view 并不在navigaitonController的控制之下,所以你需要在model view里也添加下面的代码:



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


注意:

*你需要自定义一个UINavigationController的子类,这样才可以添加上述代码。

* 和UINavigationController类似,tab controller里的各个view的orientation设置应该放在tab controller里

对于 ios6的top-most controller决定orientation设置,导致这样一个问题:在 top-most controller里的views无法拥有不相同的orientation设置。例如:在nav controller里,你有main view, sub view and sub sub view,前2个都只能是竖屏,而sub sub view是用来播放视频的,可以横竖屏。那么在ios 4 and 5里可以通过在main view and sub view的shouldAutorotateToInterfaceOrientation里设置只能竖屏,而在sub sub view的shouldAutorotateToInterfaceOrientation设置横竖屏即可。而在ios 6里则无法实现这种效果,因为在main view, sub view and sub sub view的orientation设置是无效的,只能够在nav controller里设置。那么你可能想着用下列代码在nav controller里控制哪个view竖屏,哪个view横屏

-(NSUInteger)supportedInterfaceOrientations{  
    if([[self topViewController] isKindOfClass:[SubSubView class]])  
        return UIInterfaceOrientationMaskAllButUpsideDown;  
    else  
        return UIInterfaceOrientationMaskPortrait;  
}  


是的,这样可以使得在main view and sub view里无法横屏,而sub sub view横竖屏都行。但问题来了,如果在sub sub view时横屏,然后back to sub view,那么sub view是横屏显示的!

目前想到的解决方法只能是把sub sub view脱离nav controller,以modal view方式来显示。这样就可以在modal view里设置横竖屏,而在nav controller里设置只竖屏。


* 说了那么多,其实如果你的app的所有view的orientation的设置是统一的,那么你可以简单的在plist file里设置即可,不用添加上面的代码。而如果你添加了上面的代码,就会覆盖plist里orientation的设置。


* in iOS 6, 当view controller present时,不会call willRotateToInterfaceOrientation:duration:, willAnimateRotationToInterfaceOrientation:duration:, and didRotateFromInterfaceOrientation: methods,只有在发生rotate的时候才会call


以上资料的参考了别人的博文和自己在适配ios6转屏的一些心得
感谢

Tomson Xu


你可能感兴趣的:(旧工程适配ios6和iphone5 之 适配ios6转屏)