Swift 中的 CGRect, CGSize, CGPoint

语法风格

我们平常在使用 CGGeometry 结构体时, 很多情况下会习惯性使用下面的写法

CGGeometry 结构体指的是 CGRect, CGSize, CGPoint

let rect = CGRectMake(0, 0, 100, 100)
let point = CGPointMake(0, 0)
let size = CGSizeMake(100, 100)

这是 OC 的语法, 也可以正常运行, 有 OC 开发经验都能一眼看出这几行代码的含义, 不需要知道 CGGeometry 结构体的初始化函数中的参数名.

但是这么写的问题是它不符合 Swift 的语法风格, Swift 的语法希望对新手很友好, 并具备良好的可读性, 容易理解各个参数含义.

let rect = CGRect(x: 0, y: 0, width: 100, height: 100)
let point = CGPoint(x: 0, y: 0)
let size = CGSize(width: 100, height: 100)

另外一点好处就是参数不必局限于 CGFloat 类型了, 还可以使用 Int 和 Double 类型的参数.

Swift 语法风格的好处

  1. 代码具有良好的可读性, 可以明确参数含义
  2. 参数的类型不必局限于 CGFloat, 可以使用 Int 和 Double 类型

Zero

OC 语法风格

let rect = CGRectZero
let point = CGPointZero
let size = CGSizeZero

Swift 的语法风格

let rect = CGRect.zero
let point = CGPoint.zero
let size = CGSize.zero

获取值

以前在 OC 中用这样的代码来获取结构体中的值

CGRect frame = CGRectMake(0, 0, 100, 100)
CGFloat width = CGRectGetWidth(frame)
CGFloat height = CGRectGetHeight(frame)
CGFloat maxX = CGRectGetMaxX(frame)
CGFloat maxY = CGRectGetMaxY(frame)

为什么不能直接获取值呢?

CGFloat width = frame.size.width
CGFloat height = frame.size.height

查看 Apple 官方文档 CGGeometry Reference Documentation

考虑两个CGRect,第一个origin是[0,0],size是[10, 10]。第二个的origin是[10,10],size是[-10, -10]。两者其实是等价的,无论是OC还是Swift都支持这两种写法。问题在于,在OC中,获取结构体的属性就直接获取到它的真实值了,这个值有可能为负。所以OC建议我们调用系统API而不是直接获取值,而在Swift中,width、height等被设计为计算属性,自然就不存在这样的问题了。

For this reason, your applications should avoid directly reading and writing the data stored in the CGRect data structure. Instead, use the functions described here to manipulate rectangles and to retrieve their characteristics.

Apple, CGGeometry Reference Documentation

由于系统提供了完备的API, 不直接取值也不是什么问题. 不过 Swift 提供简单的点语法, 可以很便利的取值

let width = frame.width
let height = frame.height
let maxX = frame.maxX
let maY = frame.maxY

可变性

可以直接修改解构体的值

let frame = CGRect(x: 0, y: 0, width: 100, 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)

不用再像OC以前那样, 根据 view 的 frame 重新创建新的结构体. 然后再把 view 的 farme 改成这个结构体

CGRect frame = CGRectMake(0, 0, 100, 100);
UIView *view = [UIView alloc] initWithFrame: frame];
CGRect newFrame = view.frame;
newFrame.size.width = view.frame.origin.x + 10;
view.frame = newFrame;

以上改变还适用于 UIkit 中其他结构体

// UIEdgeInsets
var edgeInsets = UIEdgeInsets(top: 10, left: 10, bottom: 20, right: 20)
edgeInsets.top += 10

// UIOffset
var offset = UIOffset(horizontal: 10, vertical: 10)
offset.vertical += 10

可以代替默认的设置, 比如只设置结构体中某一个属性时, 不必替换整个结构体

tableView.contentInset = UIEdgeInsets(top: 100, left: 0, bottom: 0, right: 0)
tableView.contentOffset = CGPoint(x: 0, y: -100)

现在只需要

tableView.contentInset.top = 100
tableView.contentOffset.y = -100

results matching ""

    No results matching ""