在 Swift / IOS 中将 shapeLayer 添加到视图层时 Draw 应用程序滞后

Draw app is Lagging when adding shapeLayer into views layer in Swift / IOS

我正在创建一个绘图应用程序。这个应用程序允许用户在视图上绘图。我在下面给出的代码中命名该视图绘图视图。为了创建这个应用程序,我使用了 BeizerPathShapeLayer,每当用户触摸屏幕时 UIBeizerPathCAShapeLayer 初始化。这个应用程序的问题是在一些绘图视图变得滞后之后。我不知道发生了什么。有没有更好的方法来优化这个应用程序?

CanvasViewController: UIViewController {

    // MARK: Properties

    @IBOutlet weak var verticalScrollView: UIScrollView!
    var lastPoint:CGPoint?   // var mutablePath:CGMutablePath?
    var drawLine:UIBezierPath?
    var shapeLayer:CAShapeLayer?
    let dropDown = DropDown()
    var shape:CAShapeLayer?
    let listOfDropDownMenu:[String] = ["Create New Canvas","Save","Change Color"]
    var presenter: CanvasModuleInterface?

    // MARK: IBOutlets
     @IBOutlet weak var drawingView: UIView!
    @IBOutlet weak var showColorViewControllerDropDownButton: UIBarButtonItem!

    // MARK: VC's Life cycle

    override func viewDidLoad() {
        super.viewDidLoad()
        self.setup()
        self.verticalScrollView.isUserInteractionEnabled = false
    }

    // MARK: IBActions

    // MARK: Other Functions

    @IBAction func ShowColorViewControllerAction(_ sender: Any) {
         self.dropDown.anchorView = self.showColorViewControllerDropDownButton
         self.dropDown.dataSource = self.listOfDropDownMenu
        self.dropDown.selectionAction = { [unowned self] (index: Int, item: String) in
            switch index{
            case 0:
              self.createNewView()
            case 1:
              self.saveTheCanvas()
            case 2:
             self.presentToColorViewController()

            //self.presentColorController()
            default:
                print("out of order !!!")
            }

        }
        self.dropDown.show()
    }

    private func createNewView(){
        //Mark: - create new canvas
        self.drawingView.layer.sublayers!.forEach { (layers) in
            layers.removeFromSuperlayer()
        }
    }
    private func presentToColorViewController(){
        // Mark : - naviagate to color view controller.


    }
    private func saveTheCanvas(){
        // Mark: - save the drawing

    }

    private func setup() {
        // all setup should be done here
    }
    private func presentColorController(){
        let colorSelectionController = EFColorSelectionViewController()
        let colorNavigationController = UINavigationController(rootViewController: colorSelectionController)
        colorNavigationController.navigationBar.backgroundColor = UIColor.white
        colorNavigationController.navigationBar.isTranslucent = false
        colorNavigationController.modalPresentationStyle = UIModalPresentationStyle.popover
        colorSelectionController.delegate = self
        colorSelectionController.color = self.view.backgroundColor ?? UIColor.white

        if UIUserInterfaceSizeClass.compact == self.traitCollection.horizontalSizeClass {
            let doneButton: UIBarButtonItem = UIBarButtonItem(
                title: NSLocalizedString("Done", comment: ""),
                style: UIBarButtonItem.Style.done,
                target: self,
                action: #selector(dismissViewController)
            )
            colorSelectionController.navigationItem.rightBarButtonItem = doneButton
        }
        self.present(colorNavigationController, animated: true, completion: nil)
    }
    @objc func dismissViewController(){
        //##ask confusion.....
        self.dismiss(animated: true, completion: nil)
    }

}

// MARK: CanvasViewInterface extension CanvasViewController: CanvasViewInterface {
     } extension CanvasViewController: EFColorSelectionViewControllerDelegate{
    func colorViewController(_ colorViewCntroller: EFColorSelectionViewController, didChangeColor color: UIColor) {

    } } extension CanvasViewController{

    //Mark: - this extension contains function for drawing the circle.
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        print("touches begin")

        self.drawLine = UIBezierPath()
        self.shapeLayer = CAShapeLayer()
        //       self.mutablePath = CGMutablePath()

        if let touchesPoint = touches.first{
            self.lastPoint = touchesPoint.location(in: self.drawingView)
         }

    }
    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
         //        self.drawingView.layer.sublayers!.forEach { (layer) in //            print(layer) //        }
      //  print(self.drawingView.layer)

    }
    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?){ //        print("\(self.drawingView)") //        print("\(self.drawingView.layer.sublayers)")

        var nextPoint:CGPoint?
        if let touchesPoint = touches.first{
            nextPoint = touchesPoint.location(in: self.drawingView)
            guard let lastLinePoint = self.lastPoint , let nextLinePoint = nextPoint else{return}
            self.drawLineInDrawingView(from: lastLinePoint, to: nextLinePoint)
        }
        if let newPoint = nextPoint{
        self.lastPoint  = newPoint
        }
    }
    func drawLineInDrawingView(from:CGPoint,to:CGPoint){
        drawLine!.move(to: CGPoint(x: from.x, y: from.y))
        drawLine!.addLine(to: CGPoint(x: to.x, y:  to.y))
        shapeLayer!.path = drawLine!.cgPath
        shapeLayer!.strokeColor = UIColor.black.cgColor
        shapeLayer!.lineCap = .round
        shapeLayer!.lineWidth = 100
        self.drawingView.layer.addSublayer(shapeLayer!)    //     print(self.drawingView.layer.sublayers)
    }
     }

不知道 CanvasViewController 你在用什么,不能完全正确地回答你的问题,但我会回答,假设它的工作方式类似于 iOS 中的任何常规 UIView。

有几点我可以指出来提高性能:

首先,不要将相同的 ShapeLayerdrawLineInDrawingView(from:CGPoint,to:CGPoint) 中一遍又一遍地添加到绘图视图中,而是只在 touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) 中添加一次并存储对它。

其次,您的 drawLineInDrawingView(from:CGPoint,to:CGPoint) 应该如下所示:

func drawLineInDrawingView(from:CGPoint,to:CGPoint){
    CATransaction.begin()
    CATransaction.setDisableActions(true)

    drawLine!.move(to: CGPoint(x: from.x, y: from.y))
    drawLine!.addLine(to: CGPoint(x: to.x, y:  to.y))
    shapeLayer!.path = drawLine!.cgPath
    shapeLayer!.strokeColor = UIColor.black.cgColor
    shapeLayer!.lineCap = .round
    shapeLayer!.lineWidth = 100
    shapeLayer!.setNeedsDisplay()

    CATransaction.commit()
}

总而言之:在 touchesBegan() 之后,您添加了 shapeLayer 并存储了对它的引用。在 touchesMoved 中,您调用 drawLineInDrawingsFunction。 您的 drawLineInDrawingsFunction,仅使用 shapeLayer.setNeedsDisplay().

更新您的 Shapelayer

将你的转换放在里面

CATransaction.begin()
CATransaction.setDisableActions(true)
/**Your transformation here**/
CATransaction.commit()

只是为了阻止您的视图自动动画更改,而是立即显示它们。

希望对您有所帮助。