将 UIColor 与 CAShapeLayer 一起使用

Using UIColor with CAShapeLayer

我将 RGB 颜色传递给 shapeLayer.fillColorshapeLayer.strokeColor,但我的代码崩溃了。这是我尝试过的:

let shapeLayer = CAShapeLayer()
shapeLayer.fillColor = (UIColor(red: 57, green: 65, blue: 101, alpha: 1) as! CGColor)
shapeLayer.strokeColor = (UIColor(red: 57, green: 65, blue: 101, alpha: 1) as! CGColor)

如果我将 RGB 颜色写为:

UIColor(red: 57, green: 65, blue: 101, alpha: 1)

Xcode 警告我将其更改为:

(UIColor(red: 57, green: 65, blue: 101, alpha: 1) as! CGColor)

当我 运行 Xcode 建议的修复时,我的应用程序崩溃了。为什么?

首先,参数 redgreenbluealpha 必须在 0.0 到 1.0 的范围内

其次,您必须将 cgColor 传递给 CGLayer,例如

let color = UIColor(red: 57.0/255.0, green: 65.0/255.0, blue: 101.0/255.0, alpha: 1)
shapeLayer.fillColor = color.cgColor
shapeLayer.strokeColor = color.cgColor

您将 UIColor 类型转换为 CGColor 是错误的。并且RGB值必须在0.0到1.0之间,检查下面的代码。

let circlePath = UIBezierPath(arcCenter: CGPoint(x: bounds.origin.x+60,y: bounds.origin.y+107), radius: CGFloat(6), startAngle: CGFloat(0), endAngle:CGFloat(7), clockwise: true)

let shapeLayer = CAShapeLayer()
shapeLayer.path = circlePath.cgPath
circlePath.lineCapStyle = .round

let color = UIColor(red: 57.0/255.0, green: 65.0/255.0, blue: 101.0/255.0, alpha: 1).cgColor

shapeLayer.fillColor = color
shapeLayer.strokeColor = color
shapeLayer.lineWidth = 3.0
self.layer.addSublayer(shapeLayer)

修复代码

你想要这样的东西:

let shapeLayer = CAShapeLayer()
shapeLayer.fillColor = UIColor(red: 57, green: 65, blue: 101, alpha: 1).cgColor
shapeLayer.strokeColor = UIColor(red: 57, green: 65, blue: 101, alpha: 1).cgColor

工作原理

关于继承的警告

Xcode 警告您有关 某事 的分配是正确的,因为您分配的是 UIColor to a CGColor 属性,但是 "fix-me"建议是错误的。 (Xcode 可能会这样做,因为它发现 class 名称相似,但不完全相同。可能值得提交雷达。)

您会经常看到的一个地方是将自定义 UITableViewCell subclass 类型转换为基本单元格 class,但这在这里行不通。 CGColor 不继承自 UIColorUIColor 也不继承自 CGColor。 CGColor 是 CFTypeRef 而 UIColor 继承自 `NSObject.

其中一个与另一个不同

现在,为什么这些颜色不同?

CG 代表 "Core Graphics" 并且比定义 UIColor class 的 UIKit 处于较低级别。一种颜色 object 是 UIKit 的一部分,也是 Core Graphics 的一部分。

文档说 UIColor 是:

An object that stores color data and sometimes opacity (alpha value)."

再往下一点,概述说 UIColor 在内部将自己表示为预定颜色 space 内的 CGColor

另一方面,

CGColor 是:

A set of components that define a color, with a color space specifying how to interpret them."

在概念上,非常相似,但不完全相同。 UIColor 在 sRGBA space (as noted here) 中定义,但 CGColor 将包含有关颜色 space 的信息。

现在,您正在使用的动画层是 Core Animation 的一部分,Core Animation 是另一个 Apple 框架。 Core Animation 不是 UIKit 的一部分,它也不是 "on top of" UIKit,所以它的 classes 不使用 UIColor。 Core Animation 使用 CGColor 表示颜色。

UIColor 很容易实例化,不过,我们大部分时间都在 UIKit-land 中。在 UIViewUIViewController 中工作时,我们如何自定义 CALayer 和朋友?幸运的是,UIColor 公开了自身的 CGColor 版本,带有 .cgColor 属性.

关于颜色空间的注意事项

其他一些答案指出您需要传递介于 0.0 和 1.0 之间的值。这是事实,但值得注意的是,从 iOS 10 开始,Apple 已向 iOS.

添加了一些 wider-color 功能

这意味着实际上可以传入小于 0.0 和大于 1.0 的值。来自 UIColor documentation:

When working in an extended color space, color values are not clamped to fit inside the color gamut, meaning that component values may be less than 0.0 or greater than 1.0. When displayed on an sRGB display, such colors are outside the gamut and will not be rendered accurately.

您现在可能不需要担心颜色 space,但是如果您想做一些超出在屏幕上显示颜色之外的事情,了解基本原理很重要。 (生成反色或互补色是一些示例。)

Session 712 from WWDC 2016 (link) 深入介绍了这个新的 API,我建议您在熟悉基础知识后再看一看。

最后,有一个 Apple Tech Note (TN2313) 比我想象的更深入地讨论了这个问题。如果您想在 iOS macOS 上了解很多关于颜色和颜色 space 的知识,请阅读标题为 "Best Practices for Color Management in OS X and iOS."[=42 的技术说明=]