Swift: CGRect,CGSize & CGPoint
引言:你可能在Swift中没有正确使用
当我第一次决定完全使用Swift语言以来,已经快有8个月了。在这段时间里我慢慢的在Swift语言中停止使用一些Objective-C风格的代码方式,转而适应和使用新语言中的一些特性。
但是有一件事,我最近才发现。那就是我一直在CGGeometry结构中使用非Swift语言风格的丑陋样式。
CGRect,CGSize,CGPoint
C语言风格。穿着狼皮的羊
我有一个强烈的感觉,那就是很多Swift语言的开发组都会犯下面的错误。如果你曾经写出个下面形式的代码,请举起你的手来。
let rect = CGRectMake(0,100,100) let point = CGPointMake(0,0) let size = CGSizeMake(100,100)
是的,我也曾这样写过。但是不需要担心,这并不是什么羞耻的事。
上面代码的错误原因是代码风格不符合Swift语言的约定。虽然该代码能够正确编译运行,但是这个风格更像Objective-C中的风格,甚至可以说像Java的风格。
对于一个有经验的iOS和OSX的开发者来说,只需要扫一眼他们就能告诉你这段代码的作用。他们不需要你表明CGGeometry中的参数,因为他们早就知道其中参数的意义以及参数之间的顺序。但是对于初学者,则不那么容易。
关于Swift中的很多特性对于刚接触学习的新手或者刚刚入门的人们来说都是很友好的。因为对于这些人来说,可能一开始他们并不知道这些数字到底代表的意思。所以,让我们按照Swift中的特性和风格写出如下代码:
let rect = CGRect(x: 0,y: 0,width: 100,height: 100) let size = CGSize(width: 100,height: 100) let point = CGPoint(x: 0,y: 0)
通过添加一些额外的语法,虽然让代码变的冗余了一些,但是每个人第一次看过去都能立刻理解代码的意义。这样初始化CGGeometry结构的好处是,除了使用CGFloat作为参数外,我们还可以使用Int和Double。
Zero
let rect = CGRectZero let size = CGSizeZero let point = CGPointZero
既然上面已经提到风格问题,但是你仍然可能可能写出这种代码,对不对呢?
当然我们也可以将上面的代码更新为更新式、Swift化的代码。新风格的代码仅仅多了一个字符。代码如下:
let rect = CGRect.zero let size = CGSize.zero let point = CGPoint.zero
另一个能帮助你使用这个特征的地方就是,Xcode的语法高亮会提示".zero"(取决于不同的配色方案,高亮显示会不同)。
值检索
CGRect frame = CGRectMake(0,100) CGFloat width = CGRectGetWidth(frame) CGFloat height = CGRectGetHeight(frame) CGFloat maxX = CGRectGetMaxX(frame) CGFloat maxY = CGRectGetMaxY(frame)
如果你依旧是一个好的Objective-C的使用者,当你想得到rect中的某个特殊值你可以使用值的getter方法。但是,为什么我们不直接访问这些值呢?
因为这个原因(调用函数的时候会默认进行标准化),你的程序应该避免直接读写存储在CGRect数据结构中的数据。相反,应该使用这里的描述的函数去操作矩形并检索特征。
这里依旧有很多东西并没有这些手续那样麻烦,但是没有关系。Swift为我们提供了这样一个不完美的API并提供了一个简单的点符号变量。
let frame = CGRect(x: 0,height: 100) let width = frame.width let height = frame.height let maxX = frame.maxX let maxY = frame.maxY
作为补充,我还提供了很多这种细微的例子的*Swift Playgrounds程序。链接在文章的最下面。
可变性
let frame = CGRect(x: 0,height: 100) let view = UIView(frame: frame) view.frame.origin.x += 10
你不仅可能修改某个视图框架的各个值,还有可能将子结构完整的替换掉。例如:
let view = UIView(frame: .zero) view.frame.size = CGSize(width: 10,height: 10) view.frame.origin = CGPoint(x: 10,y: 10)
仅仅是上面这个小小的特征就已经足够让你停止使用Objective-C了。我们不需要重新创建一个CGRect并设置新值来完成对它的改变。仅仅不到两年之前,当我们还在使用Objective-C的时候完成上面的功能我们不得不写出如下代码:
CGRect frame = CGRectMake(0,100); UIView *view = [[UIView alloc] initWithFrame: frame]; CGRect newFrame = view.frame; newFrame.size.width = view.frame.origin.x + 10; view.frame = newFrame;
我不知道你的感受,但是这样编写代码让我感到紧张。首先,从视图View中创建新框架,然后修改框架的值,最好将新框架重新设置回视图View的.frame属性中。不,谢谢,我永远都不想再这样写代码了。
不要忘了
在UIKit中还有一些其它的结构同样适用这些改变:
UIEdgeInsets
var edgeInsets = UIEdgeInsets(top: 10,left: 10,bottom: 10,right: 10) edgeInsets.top += 10
UIOffset
var offset = UIOffset(horizontal: 10,vertical: 10) offset.vertical += 10