iOS开发中的方向包含两个:设备方向(Device orientation),界面方向(Interface orientation)
设备方向
也就是手机的方向,对应于枚举UIDeviceOrientation
typedef enum {
UIDeviceOrientationUnknown,
UIDeviceOrientationPortrait,
UIDeviceOrientationPortraitUpsideDown,
UIDeviceOrientationLandscapeLeft,
UIDeviceOrientationLandscapeRight,
UIDeviceOrientationFaceUp,
UIDeviceOrientationFaceDown
} UIDeviceOrientation;
LandscapeRight:with the device held upright and the home button on the left side

FaceUp

界面方向
对应于枚举UIInterfaceOrientation
typedef enum : NSInteger {
UIInterfaceOrientationUnknown = UIDeviceOrientationUnknown,
UIInterfaceOrientationPortrait = UIDeviceOrientationPortrait,
UIInterfaceOrientationPortraitUpsideDown = UIDeviceOrientationPortraitUpsideDown,
UIInterfaceOrientationLandscapeLeft = UIDeviceOrientationLandscapeRight,
UIInterfaceOrientationLandscapeRight = UIDeviceOrientationLandscapeLeft
} UIInterfaceOrientation;
UIInterfaceOrientation和UIDeviceOrientation大致上是对应的,但Lanscape不一样
UIInterfaceOrientationLandscapeLeft = UIDeviceOrientationLandscapeRight,
UIInterfaceOrientationLandscapeRight = UIDeviceOrientationLandscapeLeft
因为当设备处在LanscapeRight时,在调整界面时,实际上是往左旋转。
portrait:

未调整UIInterfaceOrientation

调整UIInterfaceOrientation

(对比调整前,其实界面往左旋转了)
tip
- 可通过获取状态栏的方向来查看界面方向
UIInterfaceOrientation ori = [[UIApplication sharedApplication] statusBarOrientation];
- 可通过NSNotification监听设备旋转事件
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(deviceOrientaitonChange:) name:UIDeviceOrientationDidChangeNotification object:nil];
- 如果重写shouldAutorotate使其返回NO,那么界面不会随着设备旋转,ori的值保持不变
- 当device从UIDeviceOrientationLandscapeRight旋转到UIDeviceOrientationPortraitUpsideDown时,界面方向维持为UIInterfaceOrientationLeft。 
UITraitCollection
UITraitCollection is used to describe iOS interface environment。It contains the following property:
- horizontalSizeClass
- verticalSizeClass
- displayScale(for iPhone6 plus it is 3.0)
- userInterfaceIdiom
相关枚举
UIUserInterfaceIdiom
typedef NS_ENUM(NSInteger, UIUserInterfaceIdiom) {
UIUserInterfaceIdiomUnspecified = -1,
UIUserInterfaceIdiomPhone
UIUserInterfaceIdiomPad
UIUserInterfaceIdiomTV
};
UIUserInterfaceSizeClass
UIUserInterfaceSizeClassUnspecified = 0,
UIUserInterfaceSizeClassCompact = 1,
UIUserInterfaceSizeClassRegular = 2,
UITraitEnvironment协议
- UITraitEnvironment协议中有一个UITraitCollection类型的属性traitCollection,指明interface当前所处环境
- UIScreen, UIWindow, UIViewController, UIPresentationController, UIView都遵循了这个协议
traitCollectionDidChange:
- 当interface environment改变的时候,该方法会被调用
- 结合前面对UIInterfaceOrientation的检查,可以知道只有当设备从Portrait转换到LanscapeRight,从LanscapeLeft转换到Portrait时才会触发该方法的调用(因为其他情况下,界面的方向一直是Lanscape,UITraitCollection也就不会改变)
UIContentContainer协议
所有UIViewController和 UIPresentationController都实现了该协议
willTransitionToTraitCollection:withTransitionCoordinator:
- 次方法可用于在UI的整体环境改变后适当调整UI((usually high level presentation style)
- 如:a container view controller change the number of child view controller;
- 再如:普通的view controller可在此方法中调整view hieratchy中的视图约束
Size Class和IB
- Size Classes与Image Asset
- 在Image Asset中可为某个Image set根据不同的size class添加不同的图片;运行时SDK就将从中挑选对应的Size的图进行替换了
- 还可以将渲染选项设置为 Template Image,设置不同size下的tintcolor
//AppDlegate
[UIView appearanceForTraitCollection:[UITraitCollection traitCollectionWithHorizontalSizeClass:UIUserInterfaceSizeClassCompact]].tintColor = [UIColor redColor];
[UIView appearanceForTraitCollection:[UITraitCollection traitCollectionWithHorizontalSizeClass:UIUserInterfaceSizeClassRegular]].tintColor = [UIColor purpleColor];
- Size Classes与Interface
- 可控某些控件只出现在某些size中
- 根据size为控件设置不同的布局约束


感谢:https://onevcat.com/2014/07/ios-ui-unique/
(写得真的很赞)