CS193P:使用Swift讲座4笔记开发iOS应用
今天,我们将讨论自定义视图,特别是工程图视图。
什么是视图?
- 基本上,我们使用这些分层的矩形视图来构建UI。 视图可以有许多子视图 ,但只能有一个子 视图 。 如果您从计算器应用程序中回想起,我们的堆栈视图包含按钮的子视图,甚至其他堆栈视图。
- 我们可以使用Xcode中的界面生成器来构建视图,也可以通过编程方式来构建视图。
- UIViewController中有一个重要的属性,称为view ,它是窗口中的顶级视图。
- 请注意,当该视图旋转时,其边界将改变。 然后,我们就有机会更改此视图中的所有子视图。 此功能使我们可以根据设备的方向或大小指定视图的关系。
- 通常,尽管我们不需要此视图,因为我们倾向于将视图添加为可以直接使用的出口(@IBOutlet)。
- 那么我们如何初始化UIView? 好吧,如果您还记得在Swift中,类的初始化有很多规则,那么我们会尽量避免使用它们。 但是,如果我们不能避免它们,则有两种初始化UIView的方法,我们应该注意。
初始化(框架:CGRect)
- 如果我们以编程方式创建视图,则使用上述初始化。 如果我们选择使用接口构建器在Xcode中创建视图,则可以使用以下初始化:
初始化(编码器:NSCoder)
- 这个编码器是关于什么的。 好吧,我们使用界面生成器创建的所有视图都被编码为XML文件。 当我们运行程序时,该XML文件将被加载,并且基本上包含有关如何创建这些对象的说明。
- 如果我们需要一个视图初始化器,则需要实现这两种方法,以便无论是在代码中还是在Xcode中创建视图都可以初始化。
- 设置我们的视图的另一种方法是awakeFromNib ,该视图只有在界面构建器中创建后才能起作用。
- 每当我们在视图中处理与绘图有关的任何事情时,我们都会使用CGFloat类型。 CG代表核心图形。
- CGRects还有很多其他便利方法,我们应该很好地熟悉它们。
- 让我们看一下坐标空间。 我们将看到它不是笛卡尔坐标系。 在笛卡尔系统中,上升意味着增加y坐标的值。 在这里是不同的。
- 请注意,我们处理的是点 ,而不是像素 。 像素就像是可以在屏幕上显示的最小的光线。 一些设备的每个点有很多像素,这意味着像素被密集地包装。 这很棒,因为这意味着当我们查看曲线(如字体)时,它们不会出现锯齿状的边缘。 想想Retina显示屏上当前的Macbook和iPhone。 由于每个点压缩了多少像素,我们不能使用像素作为绘图单位,因为在密集压缩的像素设备上,我们的绘图看起来非常小,而在轻度压缩的像素上,绘图或图像会显得更大。 因此,我们得出了结论。
所有UIView中最重要的属性是 bounds 。 其余两个属性 center 和 frame 与边界混淆了,但是它们与绘制位置(边界)无关。 框架和中心与我们所处的位置有关。
- 底线是永远不要使用框架和中心绘制。 它们仅应用于将您置于您的超级视图中。
- 由于我们通常不在代码中创建视图,因此通常如何创建视图?
- 每当我们需要进行自定义绘图或处理一些自定义触摸事件时,我们都需要创建自定义视图。
- 当系统希望我们自己绘制时,系统将方法绘制发送给我们。 这是我们可以在iOS中绘制视图的唯一方法。
- 此draw方法将CGRect作为参数。 该区域是系统要我们绘制的边界中的某些子区域。 这实际上是一种性能增强,因为我们可以忽略它,并使用其边界绘制整个视图。 这可能是一个有用的区别,因为如果绘图非常昂贵,那么我们希望尽可能少地绘图。
- 我们绝不应该明确调用draw(CGRect)。 如果我们需要这样做,则应调用以下方法之一:
setNeedsDisplay()
setNeedsDisplay(_ rect:CGRect)
- 一旦我们调用了上述函数之一,最了解绘制时间的系统将实现draw(CGRect)。
- setNeedsDisplay(_ rect:CGRect)也是一种优化,因为它的rect参数是draw将使用的参数。
- 我们将使用path实现draw(CGRect)。 然后,我们抚摸并填充这些路径。 我们还使用文本和图像进行绘制,但现在让我们关注路径。 我们将选择使用UIBezierPath,这对于我们的绘图目的来说比较简单。
- 让我们花点时间只了解Core Graphics概念。
- 描边和填充是可以使我们在屏幕上看到图形的指令。 如果您想到的是字体,它实际上只是一个精致的路径。
让我们举一个真实的例子,说明如何使用UIBezierPath在屏幕上绘制三角形。
- 请注意,路径上的任何方法(例如path.move(to:CGPoint)或path.addLine(to:CGPoint))都不会在屏幕上绘制任何内容。
- 要在屏幕上绘画,我们需要描边和填充,但是要让我们看到任何东西,我们需要给它们加上颜色。
- 默认情况下,我们的视图假定完全不透明。 因此,当我们希望视图透明时,需要将视图的opaque属性设置为false。 这是性能的提高,因为显然必须使用一些计算能力来确定哪些像素可以显示出来。
- 无论如何,NSAttributedString都不是字符串。 它甚至不是NSString。 NSString是可以使用Integers索引的旧的Objective C样式String,其中Swift中的String由String.Index索引。 因此NSAttributedString是一个“字符串”,具有具有诸如颜色,字体等属性的字符。然后,我们可以在字符串或文本上调用draw(at:CGPoint)并将其绘制在屏幕上。 关于NSAttributedString的年龄的一个关键说明是,我们用来区分Swift中的可变和不可变的var和let概念不适用于它。 如果要更改它,则需要特别指出我们需要NSMutableAttributedString。