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。