let path = UIBezierPath(roundedRect: CGRectMake(0, 0, 200, 100), cornerRadius: 15)
path.CGPath.forEach { element in
switch (element.type) {
case CGPathElementType.MoveToPoint:
print("move(\(element.points[0]))")
case .AddLineToPoint:
print("line(\(element.points[0]))")
case .AddQuadCurveToPoint:
print("quadCurve(\(element.points[0]), \(element.points[1]))")
case .AddCurveToPoint:
print("curve(\(element.points[0]), \(element.points[1]), \(element.points[2]))")
case .CloseSubpath:
print("close()")
}
}
import CoreGraphics
extension CGPath {
func pathElements() -> [PathElement] {
var result = [PathElement]()
self.applyWithBlock { (elementPointer) in
let element = elementPointer.pointee
switch element.type {
case .moveToPoint:
let points = Array(UnsafeBufferPointer(start: element.points, count: 1))
let el = PathElement.moveToPoint(points[0])
result.append(el)
case .addLineToPoint:
let points = Array(UnsafeBufferPointer(start: element.points, count: 1))
let el = PathElement.addLineToPoint(points[0])
result.append(el)
case .addQuadCurveToPoint:
let points = Array(UnsafeBufferPointer(start: element.points, count: 2))
let el = PathElement.addQuadCurveToPoint(points[0], points[1])
result.append(el)
case .addCurveToPoint:
let points = Array(UnsafeBufferPointer(start: element.points, count: 3))
let el = PathElement.addCurveToPoint(points[0], points[1], points[2])
result.append(el)
case .closeSubpath:
result.append(.closeSubpath)
@unknown default:
fatalError()
}
}
return result
}
}
public enum PathElement {
case moveToPoint(CGPoint)
case addLineToPoint(CGPoint)
case addQuadCurveToPoint(CGPoint, CGPoint)
case addCurveToPoint(CGPoint, CGPoint, CGPoint)
case closeSubpath
}
let cgPath = CGPath(ellipseIn: rect, transform: nil)
let path = Path(cgPath)
path.forEach { element in
switch element {
case .move(let to):
break
case .line(let to):
break
case .quadCurve(let to, let control):
break
case .curve(let to, let control1, let control2):
break
case .closeSubpath:
break
}
}
4条答案
按热度按时间bmvo0sr51#
2017年底至今
从iOS 11、macOS 10. 13、tvOS 11和watchOS 4开始,你应该使用
CGPath
的applyWithBlock
方法。下面是一个取自this Swift package that rounds the corners of aCGPath
的真实的例子。在这段代码中,self
是一个CGPath
:Swift 3.0
在Swift 3.0中,你可以像这样使用
CGPath.apply
:Swift 2.2
通过添加
@convention(c)
,现在可以直接从Swift调用CGPathApply
。下面是一个可以实现必要功能的 Package 器:(Note我的代码中没有提到
@convention(c)
,但在Core Graphics模块中的CGPathApply
声明中使用了它。示例用法:
eagi6jfj2#
(Hint:如果你必须支持iOS 11之前的iOS,使用接受的答案。如果你可以要求iOS 11,这个答案就容易多了。)
从iOS 11开始,苹果官方对这个问题给出了答案:
CGPath.applyWithBlock(_:)
。这使得所有来自
CGPath.apply(info:function:)
是一个C函数,不允许以通常的快捷方式在函数中传输信息的问题的肮脏技巧变得不必要。下面的代码允许你做:
要做到这一点,复制和粘贴
或者以这段代码为例来说明如何自己使用
CGPath.applyWithBlock(_:)
。为了完整起见,以下是Apple的官方文档:https://developer.apple.com/documentation/coregraphics/cgpath/2873218-applywithblock
自iOS 13**以来,苹果官方给出了一个更优雅的答案:使用
SwiftUI
(即使您的UI不在SwiftUI
中)将
cgPath
转换为SwiftUI Path
变量
element
的类型是Path.Element,这是一个纯Swift枚举,所以甚至不需要技巧来获取元素的值。为了完整起见,以下是Apple官方文档:https://developer.apple.com/documentation/swiftui/path/3059547-foreach
qhhrdooz3#
以下是Ole Begemann的great post(感谢@Gouldsc!)的亮点,适用于Swift 3,它允许访问组成
UIBezierPath
示例的各个元素:disbfnqx4#
Dmitry Rodionov开发了一个将Swift函数转换为CFunctionPointer的函数(参见https://github.com/rodionovd/SWRoute/wiki/Function-hooking-in-Swift)。
我成功地使用了CGPathApply沿着Swift回调函数(代码为http://parker-liddle.org/CGPathApply/CGPathApply.zip),尽管正如Dmitry所说,这是一个反向工程函数,不受支持。