iOS 基础:Frames、Bounds 和 CGGeometry
https://segmentfault.com/a/1190000004695617
原文:《iOS Fundamentals: Frames, Bounds, and CGGeometry》
程康,2016 年 3 月 26 日
本文原链:【译】iOS 基础:Frames、Bounds 和 CGGeometry
如果你习惯支持点语法的语言,要搞清楚CGPoint、CGSize和CGRect并不难。不过编程式定位视图或者编写绘图代码一般都很长,因此变得很难读明白。
在这个教程里,我希望能澄清一些对 frames 和 bounds 的误解,并且介绍一下CGGeometry,它是一个结构体、常量和功能的集合,能让你更轻松地运用CGPoint,CGSize和CGRect。
1.数据类型
如果你刚开始接触 iOS 或者 OS X 开发,你可能会想CGPoint、CGSize和CGRect到底是什么。CGGeometry Reference 定义了一系列几何图元(geometric primitives)或者说结构,我们现在关注的是其中的CGPoint、CGSize和CGRect。
大多数人应该知道,CGPoint是定义了坐标系中一个点的 C 结构体。这个坐标系的原点在 iOS 的左上方以及 OS X 的左下方。换句话说,纵轴方向在 iOS 和 OS X 上不一样。
CGSize是另一个简单的 C 结构体,它定义了一个宽度值(width)和高度值(height)。CGRect包含一个origin(原点)字段、一个CGPoint和一个size(大小)字段,即一个CGSize。origin(原点)和size(大小)字段一起决定了一个矩形的位置和大小。
CGGeometry Reference 也定义了其他类型,例如CGFloat和CGVector。CGFloat就是一个float(单精度浮点型)或者double(双精度浮点型)的typedef(类型重定义),是哪一种取决于应用运行的机器结构是 32 位还是 64 位。
<!--more-->
2.Frames 和 Bounds
第一个要搞清楚的是一个视图的frame和bounds之间的区别,因为这困扰着很多 iOS 入门开发者。不过这个区别也不复杂。
在 iOS 和 OS X 中,一个应用有多个坐标系。比如,在 iOS 中应用窗口定位在屏幕的坐标系,而窗口的每一个子视图定位在窗口的坐标系。换句话说,一个视图的子视图总是定位在该视图的坐标系中。
Frames
如文档中说的,视图的frame是一个结构体,即一个CGRect,它定义了这个视图的大小和它在父视图中的位置,或者说父视图坐标系中的位置。看看下面的图应该就能明白了。

Bounds
视图的bounds属性定义了这个视图的大小和它在自身坐标系中的位置。这意味着大多数情况下一个视图的 bounds 的原点都是{0,0},如下图。视图的bounds对于绘制这个视图很重要。

当视图的frame属性被修改时,视图的center和bounds属性二者或者其一也同时被改变。
CGGeometry Reference
方便的取值方法
原文:《iOS Fundamentals: Frames, Bounds, and CGGeometry》
程康,2016 年 3 月 26 日
本文原链:【译】iOS 基础:Frames、Bounds 和 CGGeometry
如果你习惯支持点语法的语言,要搞清楚CGPoint、CGSize和CGRect并不难。不过编程式定位视图或者编写绘图代码一般都很长,因此变得很难读明白。
在这个教程里,我希望能澄清一些对 frames 和 bounds 的误解,并且介绍一下CGGeometry,它是一个结构体、常量和功能的集合,能让你更轻松地运用CGPoint,CGSize和CGRect。
1.数据类型
如果你刚开始接触 iOS 或者 OS X 开发,你可能会想CGPoint、CGSize和CGRect到底是什么。CGGeometry Reference 定义了一系列几何图元(geometric primitives)或者说结构,我们现在关注的是其中的CGPoint、CGSize和CGRect。
大多数人应该知道,CGPoint是定义了坐标系中一个点的 C 结构体。这个坐标系的原点在 iOS 的左上方以及 OS X 的左下方。换句话说,纵轴方向在 iOS 和 OS X 上不一样。
CGSize是另一个简单的 C 结构体,它定义了一个宽度值(width)和高度值(height)。CGRect包含一个origin(原点)字段、一个CGPoint和一个size(大小)字段,即一个CGSize。origin(原点)和size(大小)字段一起决定了一个矩形的位置和大小。
CGGeometry Reference 也定义了其他类型,例如CGFloat和CGVector。CGFloat就是一个float(单精度浮点型)或者double(双精度浮点型)的typedef(类型重定义),是哪一种取决于应用运行的机器结构是 32 位还是 64 位。
<!--more-->
2.Frames 和 Bounds
第一个要搞清楚的是一个视图的frame和bounds之间的区别,因为这困扰着很多 iOS 入门开发者。不过这个区别也不复杂。
在 iOS 和 OS X 中,一个应用有多个坐标系。比如,在 iOS 中应用窗口定位在屏幕的坐标系,而窗口的每一个子视图定位在窗口的坐标系。换句话说,一个视图的子视图总是定位在该视图的坐标系中。
Frames
如文档中说的,视图的frame是一个结构体,即一个CGRect,它定义了这个视图的大小和它在父视图中的位置,或者说父视图坐标系中的位置。看看下面的图应该就能明白了。
Bounds
视图的bounds属性定义了这个视图的大小和它在自身坐标系中的位置。这意味着大多数情况下一个视图的 bounds 的原点都是{0,0},如下图。视图的bounds对于绘制这个视图很重要。
当视图的frame属性被修改时,视图的center和bounds属性二者或者其一也同时被改变。
CGGeometry Reference
方便的取值方法
之前提到过,CGGeometry Reference 是一个让运用坐标和矩形更方便的结构体、常量和方法的集合。你可能碰到过类似的下面的代码片段:
CGPoint point = CGPonitMake(self.view.frame.origin.x + self.view.frame.size.width, self.view.frame.origin.y + self.view.frame.size.height);
这样的片段不尽难阅读,而且过于冗长。我们可以用在 CGGeometry Reference 中定义的两个方便的方法重写这段代码。
CGRect frame = self.view.frame;
CGPoint point = CGPointMake(CGRectGetMaxX(frame), CGRectGetMaxY(frame));
为了简化之前那段代码,我们把视图的frame储存到一个叫frame的变量中,并且使用了CGRectGetMaxX和CGRectGetMaxY两个方法。这两个方法的方法名解释了自己的功能。
CGGeometry Reference 定义了返回一个矩形 x 轴坐标、y 轴坐标最小和最大值以及这个矩形中心坐标的方法。另外两个方便的取之方法是`CGRectGetWidth
和CGRectGetHeight`。
创建结构体
当要创建CGPoint、CGSize和CGRect时,大多数人都用CGPointMake或者类似的方法。这些方法也被定义在 CGGeometry Reference 中。虽然它们的实现非常简单,它们特别有用并且让你少写一些代码。例如,CGRectMake是这样实现的:
CGRectMake(CGFloat x, CGFloat y, CGFloat width, CGFloat height)
{
CGRect rect;
rect.origin.x = x; rect.origin.y = y;
rect.size.width = width; rect.size.height = height;
return rect;
}
修改矩形
以上提到过的方法都是 iOS 开发者熟知的,它们减少了我们的代码量并且让它们可读性增加。不过,CGGeometry Reference 也定义了一切其他大家不太了解的方法。比如 CGGeometry Reference 定义了一堆修改CGRect结构的方法。让我们来看看其中一些。
CGRectUnion
CGRectUnion接受两个CGRect结构体作为参数并且返回一个能够包含这两个矩形的最小矩形。听起来可能没什么,我相信你也可以用几行代码轻松实现这个功能,不过 CGGeometry 做的是给你提供一些方法让你的代码更干净、可读性更强。
如果你把下面代码片段加到一个 view controller 的viewDidLoad方法中,你将在模拟器中看到如下结果。那个灰色的矩形就是使用CGRectUnion的结果。
// CGRectUnion
CGRect frame1 = CGRectMake(80.0, 100.0, 150.0, 240.0);
CGRect frame2 = CGRectMake(140.0, 240.0, 120.0, 120.0);
CGRect frame3 = CGRectUnion(frame1, frame2);
UIView *view1 = [[UIView alloc] initWithFrame:frame1];
[view1 setBackgroundColor:[UIColor redColor]];
UIView *view2 = [[UIView alloc] initWithFrame:frame2];
[view2 setBackgroundColor:[UIColor orangeColor]];
UIView *view3 = [[UIView alloc] initWithFrame:frame3];
[view3 setBackgroundColor:[UIColor grayColor]];
[self.view addSubview:view3];
[self.view addSubview:view2];
[self.view addSubview:view1];
CGRectDivide
另一个有用的方法是CGRectDivide,它帮你把一个给定矩形分割成两个。看看下面的代码和截图来了解它是怎么运作的。
// CGRectDivide
CGRect frame = CGRectMake(10.0, 50.0, 300.0, 300.0);
CGRect part1;
CGRect part2;
CGRectDivide(frame, &part1, &part2, 100.0, CGRectMaxYEdge);
UIView *view1 = [[UIView alloc] initWithFrame:frame];
[view1 setBackgroundColor:[UIColor grayColor]];
UIView *view2 = [[UIView alloc] initWithFrame:part1];
[view2 setBackgroundColor:[UIColor orangeColor]];
UIView *view3 = [[UIView alloc] initWithFrame:part2];
[view3 setBackgroundColor:[UIColor redColor]];
[self.view addSubview:view1];
[self.view addSubview:view2];
[self.view addSubview:view3];
如果你不使用CGRectDivide来计算红色和橙色矩形的话,你可能要多谢几十行代码。不信你就试试。
比较和包含
用下面六个方法来比较几何结构和检查包含关系非常简单。
- CGPointEqualToPoint
- CGSizeEqualToSize
- CGRectEqualToRect
- CGRectIntersectsRect
- CGRectContainsPoint
- CGRectContainsRect
CGGeometry Reference 还有一些其他宝贝,比如CGPointCreateDictionaryRepresentation可以用来将一个 CGPoint 结构体转换为一个 CGDictionaryRef,CGRectIsEmpty可以用来检查一个矩形的宽高是否都为零。更多详情请看[《CGGeometry Reference 文档》]()。
4.福利:打印日志
在 Xcode 控制台打印日志如果没有一些辅助方法的话很麻烦。幸运的是,UIKit 框架定义了一些让它变得很方便的方法。我天天用它们。看看下面的代码片段来了解它们是如何工作。并没有什么奇特的。
CGPoint point = CGPointMake(10.0, 25.0);
CGSize size = CGSizeMake(103.0, 223.0);
CGRect frame = CGRectMake(point.x, point.y, size.width, size.height);
NSLog(@"\n%@\n%@\n%@", NSStringFromCGPoint(point), NSStringFromCGSize(size), NSStringFromCGRect(frame));
还有一些方便打印仿射变换(affine transforms)(NSStringFromCGAffineTransform)、边缘插入(NSStringFromUIEdgeInsets)、偏移(NSStringFromUIOffset)等的日志的方便方法。
总结
iOS SDK 包含了大量开发者们不了解的宝贝。我希望我给你们讲明白了 CGGeometry Reference 的实用性。一旦你开始使用它的那些方法,你就会开始问自己,以前没用它怎么活过来的。
iOS 基础:Frames、Bounds 和 CGGeometry的更多相关文章
- IOS基础学习-2: UIButton
IOS基础学习-2: UIButton UIButton是一个标准的UIControl控件,UIKit提供了一组控件:UISwitch开关.UIButton按钮.UISegmentedContro ...
- iOS 基础日记-修饰符
今晚随便温习了一下iOS 基础关于修饰符这块的东西,下面简单的来描述一下,其中有的也是在网络学习到的: strong与weak是由ARC新引入的对象变量属性 ARC的解释:ARC引入了新的对象的生命周 ...
- iOS基础问答面试
<简书社区 — Timhbw>iOS基础问答面试题连载(一)-附答案:http://www.jianshu.com/p/1ebf7333808d <简书社区 — Timhbw> ...
- [iOS基础控件 - 5.5] 代理设计模式 (基于”APP列表"练习)
A.概述 在"[iOS基础控件 - 4.4] APP列表 进一步封装,初见MVC模式”上进一步改进,给“下载”按钮加上效果.功能 1.按钮点击后,显示为“已下载”,并且不 ...
- [置顶] IOS 基础入门教程
IOS 基础入门教程 教程列表: IOS 简介 IOS环境搭建 Objective C 基础知识 创建第一款iPhone应用程序 IOS操作(action)和输出口(Outlet) iOS - 委托( ...
- iOS 基础入门--Bull' Eye 小游戏
说明 Bull's Eye小游戏是http://www.raywenderlich.com/store/ios-apprentice里非常酷的入门demo 跟着该教程一步步做下来便有了 ...
- iOS 基础函数解析 - Foundation Functions Reference
iOS 基础函数解析 - Foundation Functions Reference 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名- ...
- 动画 iOS基础
动画 iOS基础 1. basic animation 基础动画 一个基础动画 在一个开始值和一个结束值之间运动 messageLabel.alpha=0.0; [UIView ani ...
- iOS基础UI控件介绍-Swift版
iOS基础UI控件总结 iOS基础控件包括以下几类: 1.继承自NSObject:(暂列为控件) UIColor //颜色 UIImage //图像 2.继承自UIView: 只能相应手势UIGest ...
随机推荐
- C# 如何获取Url的host以及是否是http
参考资料:https://sites.google.com/site/netcorenote/asp-net-core/get-scheme-url-host Example there's an g ...
- 简述ADO.NET(一)
ADO.NET 宏观定义 传统ADO主要针对紧密连接的客户端/服务器端系统,而 ADO.NET考虑到了断开连接式应用并且引进了 Dateset 它代表任意数量的关联表,其中每个表都包含了行和列的集合的 ...
- asp.net 建多个项目实现三层的实例——读取一张表中的记录条数
学习asp.net两周,通过学习发现,.net和php之间的区别还是蛮大的,比php要复杂一些,开始学习的有些吃力,后来跟着传智播客里的老师学习,渐渐的学到了一些东西. 今天要记录一下.net里的简单 ...
- 【Unity】微软的一款依赖注入组件
前言 前面学习了autofac这个依赖注入组件,本来是打算写在一起的,因为这个组件没打算像autofac一样详细的写,只是写下以前自己鼓捣玩搭建框架然后使用的一个依赖注入组件,并且也是进行了封装使用. ...
- C# 操作Word书签(二)——插入图片、表格到书签;读取、替换书签
概要 书签的设置可以帮助我们快速的定位某段文字,使用起来很方便,也很节省时间.在前一篇文章“C# 如何添加/删除Word书签”中介绍了插入.删除书签的方法,本篇文章将对C# 操作Word书签的功能做进 ...
- 结合JDK源码看设计模式——简单工厂、工厂方法、抽象工厂
三种工厂模式的详解: 简单工厂模式: 适用场景:工厂类负责创建的对象较少,客户端只关心传入工厂类的参数,对于如何创建对象的逻辑不关心 缺点:如果要新加产品,就需要修改工厂类的判断逻辑,违背软件设计中的 ...
- OO_BLOG1_简单表达式求导问题总结
作业1-1 包含简单幂函数的多项式导函数的求解 I. 基于度量的程序结构分析 1)程序结构与基本度量统计图 2)分析 本人的第一次作业的程序实现逻辑十分简单,但是OOP的色彩并不强烈,程序耦合度过 ...
- nginx系列1:认识nginx
nginx介绍 nginx是什么呢?可以看下官方网站的定义: nginx [engine x] is an HTTP and reverse proxy server, a mail proxy se ...
- 关于ArcMap中打开ArcToolbox导致闪退的解决办法
最近好久不用ArcGis的小编要用到ArcMap去发送一个GP服务,发现按照套路打开ArcMap点击ArcToolbox时,发生了ArcMap的闪退现象,几经周折终于解决了问题. 希望也遇到这类问题的 ...
- DVWA 黑客攻防演练(八)SQL 注入 SQL Injection
web 程序中离不开数据库,但到今天 SQL注入是一种常见的攻击手段.如今现在一些 orm 框架(Hibernate)或者一些 mapper 框架( iBatis)会对 SQL 有一个更友好的封装,使 ...