首页 » iOS编程(第4版) » iOS编程(第4版)全文在线阅读

《iOS编程(第4版)》17.8 深入学习:位掩码

关灯直达底部

本章之前介绍了supportedInterfaceOrientations方法,其返回值决定了视图控制器可以支持的所有界面方向。虽然supportedInterfaceOrientations方法仅仅返回单一整形值,但是这个整形值仍然可以囊括四种界面方向中的任意一种或几种。如何使用单一值描述多种可能值?答案是位掩码(bitmasks)。

使用位掩码可以避免为保存每一种可能值而创建大量的属性。例如,在不使用位掩码的情况下,如果要表示视图控制器所支持的界面方向,可能会添加下列四个属性:

@property (nonatomic, assign) BOOL canRotateToLandscapeLeft;

@property (nonatomic, assign) BOOL canRotateToLandscapeRight;

@property (nonatomic, assign) BOOL canRotateToPortrait;

@property (nonatomic, assign) BOOL canRotateToPortraitUpsideDown;

界面方向只有四种,需要添加四个属性,而iOS中还有大量的类具有存在更多可能值的选项。例如UIView,如果打开其头文件,可以看见其动画选项UIViewAnimationOptions具有数十种可能值(本书第27章会介绍动画)。相反,使用位掩码,只需要单一整形值就可以存储任意数量的可能值。

位掩码会将各个值表示为一系列开关,其原理是:计算机是使用二进制格式存储数据的,二进制数据是由一系列0和1组成的。下面列出的是若干以10为基数的数(十进制是我们使用的数字进制)和相应的以2为基数的数(二进制是计算机使用的数字进制)。

110 = 000000012

210 = 000000102

1610 = 000100002

2710 = 000110112

3410 = 001000102

二进制数字中的列称为二进制位(bit)。可以将二进制位想象成开关,1代表“开”,0代表“关”。这样就可以将int类型的整数(至少会占用32个二进制位)想成是一组开关。数字的每个位代表一个“开关”:1代表“开(真)”,0代表“关(假)”。这等于是将很多布尔值塞进了一个整数。

在以上数字中,1、2和16都是2的n次幂(分别是0次幂、1次幂和4次幂)——只有一个二进制位是1(其余都是0)。而27和34不是2的n次幂,其二进制数值中有多个1。可以用这类数值为2次幂的数字来代表位掩码中的“开关”,每个开关称为一个掩码。

例如,以下是所有界面方向的位掩码:

UIInterfaceOrientationMaskPortrait = 210 = 000000102

UIInterfaceOrientationMaskPortraitUpsideDown = 410 = 000001002

UIInterfaceOrientationMaskLandscapeRight = 810 = 000010002

UIInterfaceOrientationMaskLandscapeLeft = 1610 = 000100002

用按位或(|)运算符可以“打开”位掩码中的某个“开关”。执行按位或运算时需要两个数字,只要这两个数字位于同一列上的值有一个是1,那么生成的数字的相应列的值也会是1。将某个数字和一个值为2n的数字进行按位或运算时,第n位的“开关”就会打开。例如,按位或1和16,会得到如下结果:

00000010 ( 210,UIInterfaceOrientationMaskPortrait)

|00010000 (1610,UIInterfaceOrientationMaskLandscapeLeft)

----------

00010010 (1810,同时包含UIInterfaceOrientationMaskPortrait

和UIInterfaceOrientationMaskLandscapeLeft)

和按位或运算符相对的是按位与(&)运算符。执行按位与运算时需要两个数字,只有当这两个数字位于同一列上的值都是1时,生成的数字的相应列的值才会是1。

00010010 (1810,Portrait和LandscapeLeft)

&00010000 (1610,LandscapeLeft)

----------

00010000 (1610,YES)

00010010 (1810,Portrait和LandscapeLeft)

&00000100 (410,UpsideDown)

----------

00000000 (010,NO)

因为非0代表真(0代表假),所以可以用按位与运算符来检查“开关”是打开的还是关闭的。可以使用以下代码检查视图控制器所支持的界面方向:

if ([viewController supportedInterfaceOrientations]

& UIInterfaceOrientationMaskLandscapeLeft)

{

// 支持左横排方向

}