如何用 Swift 填充 UIBezierPath 的内部?

How can I fill the inside of a UIBezierPath with Swift?

我正在尝试使用 Swift 5 填充 UIBezierPath,但是当我尝试 运行 我的函数为路径着色时,出现了很多错误。 None 其中是致命的,因此构建成功,但路径未绘制在屏幕上。我附上相关代码和两个错误。提前致谢。

func colorPaths() {    
                let path = leftCorner //Where leftCorner isa UIBezierPath

                let fillColor = UIColor.white
                fillColor.setFill()

                path.lineWidth = 1.0
                let strokeColor = UIColor.blue
                strokeColor.setStroke()

                path.fill()
                path.stroke()
            }

错误:

2020-05-25 14:35:26.653308-0400 StatsApTBD[50679:10052723] [Unknown process name] CGContextSetFillColorWithColor: invalid context 0x0. Backtrace:
  <$s10StatsApTBD8HeatViewC08changeToD4MapsyyF10colorPathsL_yyF+94>
   <$s10StatsApTBD8HeatViewC08changeToD4MapsyyF+5247>
    <$s10StatsApTBD8HeatViewC8addMarksyyF+626>
     <$s10StatsApTBD8HeatViewC21viewDidLayoutSubviewsyyF+7831>
      <$s10StatsApTBD8HeatViewC21viewDidLayoutSubviewsyyFTo+43>
       <-[UIView(CALayerDelegate) layoutSublayersOfLayer:]+3013>
        <-[CALayer layoutSublayers]+255>
         <_ZN2CA5Layer16layout_if_neededEPNS_11TransactionE+517>
          <_ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE+80>
           <_ZN2CA7Context18commit_transactionEPNS_11TransactionEd+324>
            <_ZN2CA11Transaction6commitEv+643>
             <_afterCACommitHandler+160>
              <__CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__+23>
               <__CFRunLoopDoObservers+430>
                <__CFRunLoopRun+1514>
                 <CFRunLoopRunSpecific+438>
                  <GSEventRunModal+65>
                   <UIApplicationMain+1621>
                    <main+75>
                     <start+1>                             1
2020-05-25 14:35:26.655966-0400 StatsApTBD[50679:10052723] [Unknown process name] CGContextSetStrokeColorWithColor: invalid context 0x0. Backtrace:
  <$s10StatsApTBD8HeatViewC08changeToD4MapsyyF10colorPathsL_yyF+175>
   <$s10StatsApTBD8HeatViewC08changeToD4MapsyyF+5247>
    <$s10StatsApTBD8HeatViewC8addMarksyyF+626>
     <$s10StatsApTBD8HeatViewC21viewDidLayoutSubviewsyyF+7831>
      <$s10StatsApTBD8HeatViewC21viewDidLayoutSubviewsyyFTo+43>
       <-[UIView(CALayerDelegate) layoutSublayersOfLayer:]+3013>
        <-[CALayer layoutSublayers]+255>
         <_ZN2CA5Layer16layout_if_neededEPNS_11TransactionE+517>
          <_ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE+80>
           <_ZN2CA7Context18commit_transactionEPNS_11TransactionEd+324>
            <_ZN2CA11Transaction6commitEv+643>
             <_afterCACommitHandler+160>
              <__CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__+23>
               <__CFRunLoopDoObservers+430>
                <__CFRunLoopRun+1514>
                 <CFRunLoopRunSpecific+438>
                  <GSEventRunModal+65>
                   <UIApplicationMain+1621>
                    <main+75>
                     <start+1>                             1

创建一个 CAShapeLayer 并设置路径,如下所示。

let width: CGFloat = 200
let height: CGFloat = 200

let shapeLayer = CAShapeLayer()
shapeLayer.frame = CGRect(x: 0, y: 0, width: width, height: height)

let path = leftCorner
shapeLayer.path = path
shapeLayer.strokeColor = UIColor.blue.cgColor
shapeLayer.fillColor = UIColor.white.cgColor

然后将上面的 shapeLayer 添加到您的视图中。

yourView.layer.addSublayer(shapeLayer)

这应该让您的路径显示在屏幕上。

问题是您在视图控制器上绘图,但它应该在 UIView draw(_ rect: CGRect) 方法中完成。

因此您需要子类化 UIView,覆盖 draw 方法并在那里绘制您的贝塞尔曲线路径:

import UIKit

class CanvasView: UIView {
    override func draw(_ rect: CGRect) {
        let bp = UIBezierPath(ovalIn: .init(origin: .zero, size: .init(width: 200, height: 200)))
        bp.lineWidth = 5
        UIColor.red.setFill()
        bp.fill()
        UIColor.yellow.setStroke()
        bp.stroke()
    }
}

现在您可以使用故事板或以编程方式将 CanvasView 添加到视图控制器视图中:

override func viewDidLoad() {
    super.viewDidLoad()
    let drawingView = CanvasView(frame: view.frame)
    view.addSubview(drawingView)
}