如何修复使用NSBezierPath的便捷扩展/封闭扩展以使用在Swift 5.0中失败的CGPath?

问题描述 投票:1回答:2

下面的内联是我在某处获取的用于使用方便初始化程序扩展NSBezierPath的方法,该初始化程序以CGPath作为参数,因此其行为更像iOS上的UIBezierPath

它以前可以工作,但是当我尝试在Swift 5上编译它(几年后)时,出现以下编译时错误:

C函数指针不能由捕获上下文的闭包形成

我该如何解决?

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;
        }
    })
}
swift macos swift5 cgpath nsbezierpath
2个回答
1
投票
也许类似:

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在其顶部)抚摸了他们两个。这是一种快速的经验验证,表明转换逻辑产生了相同的路径:

enter image description here

1
投票
private func transformToCGPath() -> CGPath { let path = CGMutablePath() let points = UnsafeMutablePointer<NSPoint>.allocate(capacity: 3) let numElements = self.elementCount if numElements > 0 { var didClosePath = true for index in 0..<numElements { let pathType = self.element(at: index, associatedPoints: points) switch pathType { case .moveTo: path.move(to: CGPoint(x: points[0].x, y: points[0].y)) case .lineTo: path.addLine(to: CGPoint(x: points[0].x, y: points[0].y)) didClosePath = false case .curveTo: path.addCurve(to: CGPoint(x: points[0].x, y: points[0].y), control1: CGPoint(x: points[1].x, y: points[1].y), control2: CGPoint(x: points[2].x, y: points[2].y)) didClosePath = false case .closePath: path.closeSubpath() didClosePath = true @unknown default: print("Warning! New NSBezierPath.ElementTypes() added, may affect transformToCGPath!") } } if !didClosePath { path.closeSubpath() } } points.deallocate() return path }
© www.soinside.com 2019 - 2024. All rights reserved.