首页 > 解决方案 > 如何修复 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;
        }
    })
}

标签: swiftmacosswift5cgpathnsbezierpath

解决方案


我建议使用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在白色描边中,在它上面)。这是转换逻辑产生等效路径的快速经验验证:

在此处输入图像描述


推荐阅读