swift - 如何修复 NSBezierPath 的便利 init w/closure Extension 以使用在 Swift 5.0 中失败的 CGPath?
问题描述
下面的内联是我在某处获得的一种方法,用于NSBezierPath
使用便利初始化程序进行扩展,该初始化程序将CGPath
其作为参数,使其行为更像UIBezierPath
在 iOS 上。
它以前可以工作,但是当我尝试在 Swift 5 上编译它(几年后)时,我收到以下编译时错误:
AC 函数指针不能由捕获上下文的闭包形成
我该如何解决?
convenience init(path : CGPath) {
path.apply(info: nil, function: { (_, elementPointer) in
let element = elementPointer.pointee
switch element.type {
case .moveToPoint:
let points = Array(UnsafeBufferPointer(start: element.points, count: 1))
self.move(to: points[0])
break
case .addLineToPoint:
let points = Array(UnsafeBufferPointer(start: element.points, count: 1))
self.line(to: points[0])
break
case .addQuadCurveToPoint:
let points = Array(UnsafeBufferPointer(start: element.points, count: 2))
let qp0 = self.currentPoint
let qp1 = points[0]
let qp2 = points[1]
let m = CGFloat(2.0 / 3.0)
var cp1 = NSPoint()
var cp2 = NSPoint()
cp1.x = (qp0.x + ((qp1.x - qp0.x) * m))
cp1.y = (qp0.y + ((qp1.y - qp0.y) * m))
cp2.x = (qp2.x + ((qp1.x - qp2.x) * m))
cp2.y = (qp2.y + ((qp1.y - qp2.y) * m))
self.curve(to: qp2, controlPoint1:cp1, controlPoint2:cp2)
case .addCurveToPoint:
let points = Array(UnsafeBufferPointer(start: element.points, count: 3))
self.curve(to:points[2], controlPoint1:points[0], controlPoint2:points[1])
break
case .closeSubpath:
self.close()
@unknown default:
break;
}
})
}
解决方案
我建议使用path.applyWithBlock
. 我也会失去所有那些不迅速的break
陈述,直接访问element.points
。
也许是这样的:
convenience init(path: CGPath) {
self.init()
path.applyWithBlock { elementPointer in
let element = elementPointer.pointee
switch element.type {
case .moveToPoint:
move(to: element.points[0])
case .addLineToPoint:
line(to: element.points[0])
case .addQuadCurveToPoint:
let qp0 = self.currentPoint
let qp1 = element.points[0]
let qp2 = element.points[1]
let m = CGFloat(2.0 / 3.0)
let cp1 = NSPoint(x: qp0.x + ((qp1.x - qp0.x) * m),
y: qp0.y + ((qp1.y - qp0.y) * m))
let cp2 = NSPoint(x: qp2.x + ((qp1.x - qp2.x) * m),
y: qp2.y + ((qp1.y - qp2.y) * m))
curve(to: qp2, controlPoint1: cp1, controlPoint2: cp2)
case .addCurveToPoint:
curve(to: element.points[2], controlPoint1: element.points[0], controlPoint2: element.points[1])
case .closeSubpath:
close()
@unknown default:
break
}
}
}
作为概念证明,我CGPath
使用所有不同的元素类型创建了一个,并NSBezierPath
使用上述创建了一个。然后我使用它们各自的 API 对它们进行了描边(NSBezierPath
在深蓝色描边中,CGPath
在白色描边中,在它上面)。这是转换逻辑产生等效路径的快速经验验证:
推荐阅读
- mongodb - (MongoDB Compass) 使用 let 查找不起作用
- c# - ASP.NET C# Web API:JsonConvert.SerializeObject 奇怪的“转义”数组
- typescript - 任何人都可以澄清这个打字稿手册对“keyof”的解释吗?
- django - 如何在另一个模型的视图中使用模型属性?
- php - 驾驶员警卫登录系统在laravel中不起作用
- c++ - sscanf 从八进制转换:它怎么知道?
- scala - 在 Scala 3 宏中获取封闭模块
- javascript - HTML5 视频在寻求结束时如何显示最后一个视频帧?
- html - 提取所有
- 来自具有特定类名的标签的元素
- php - 堆栈通道下 laravel 8 config/Logging.php 中的 ignore_exceptions 标志是什么