如何删除进度条圈中的 CAShapeLayer

How do I remove a CAShapeLayer in progressbar circle

我有以下代码,我正在执行它来下载带有进度圈的 PDF。

它对我有用,首先我检查文件是否已保存在 "Documents" 目录中,如果是,我只显示 PDF,如果尚未加载 pdf 文件,则 begindDownloadFile ()

lass ViewController: UIViewController, URLSessionDownloadDelegate {
    @IBOutlet weak var pdfView: PDFView!

    let urlString = "https://d0.awsstatic.com/whitepapers/KMS-Cryptographic-Details.pdf"

    let shapeLayer = CAShapeLayer()

    let percentageLabel: UILabel = {
        let label = UILabel()
        label.text = "Descargar"
        label.textAlignment = .center
        label.font = UIFont.boldSystemFont(ofSize: 16)
        return label
    }()

    override func viewDidLoad() {
        super.viewDidLoad()

        view.addSubview(percentageLabel)
        percentageLabel.frame = CGRect(x: 0, y: 0, width: 100, height: 100)
        percentageLabel.center = view.center

        //start drawing circle

        let center  = view.center

        //create the track layer, the softer color underneath the bar that it is going to fill
        let trackLayer = CAShapeLayer()
        let circularPath = UIBezierPath(arcCenter: .zero, radius: 100, startAngle: 0, endAngle: 2 * CGFloat.pi, clockwise: true)

        trackLayer.path = circularPath.cgPath
        trackLayer.strokeColor = UIColor.lightGray.cgColor
        trackLayer.lineWidth = 10 //the width of the bar
        trackLayer.fillColor = UIColor.clear.cgColor //amek the middle area have clear color
        trackLayer.lineCap = kCALineCapRound //this to make the bar has rounded corner
        trackLayer.position = center
        trackLayer.opacity = 1
        view.layer.addSublayer(trackLayer)

//        let circularPath = UIBezierPath(arcCenter: center, radius: 100, startAngle: -CGFloat.pi / 2, endAngle: 2 * CGFloat.pi, clockwise: true) //start angle like this to have the bar start at 12 o'clock
        shapeLayer.path = circularPath.cgPath
        shapeLayer.strokeColor = UIColor.red.cgColor
        shapeLayer.lineWidth = 10 //the width of the bar
        shapeLayer.fillColor = UIColor.clear.cgColor //amek the middle area have clear color
        shapeLayer.lineCap = kCALineCapRound //this to make the bar has rounded corner
        shapeLayer.strokeEnd = 0
        shapeLayer.position = center

        shapeLayer.transform = CATransform3DMakeRotation(-CGFloat.pi / 2, 0, 0, 1)

        view.layer.addSublayer(shapeLayer)

        view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleTap)))


      let myUrl = URL(string: urlString)

        // then lets create your document folder url
        let documentsDirectoryURL =  FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!

        // lets create your destination file url
        let destinationUrl = documentsDirectoryURL.appendingPathComponent((myUrl?.lastPathComponent)!)
        print(destinationUrl)


        if FileManager.default.fileExists(atPath: destinationUrl.path) {
            print("The file already exists at path")

            // hidden label and remove sublayers (circle)
            //self.percentageLabel.isHidden = true
            //shapeLayer.removeFromSuperlayer()
            //trackLayer.removeFromSuperlayer()

            trackLayer.removeFromSuperlayer()

            /************** show pdf ****************/
            let pdfUrl = destinationUrl.path
            let rutafile = URL(fileURLWithPath: pdfUrl)
            print(pdfUrl)
            if let document = PDFDocument(url: rutafile) {
                self.pdfView.autoScales = true
                self.pdfView.document = document
            }
            /************** show pdf ****************/


        } else{

             begindDownloadFile()


            }




    } // end DidLoad



    //the require func for URLSessionDownloadDelegate delegate
    func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
        print("finish downloading file")

    }

    //optional func from the delegate URLSessionDownloadDelegate
    func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
//        print(totalBytesWritten, totalBytesExpectedToWrite)
        let percentage = CGFloat(totalBytesWritten) / CGFloat(totalBytesExpectedToWrite)
        print("percentage : ", percentage)

        //this need to be in the main thread because the url session downloading is not on the main thread, so if without DispatchQueue.main, then the UI wont update
        DispatchQueue.main.async {
            self.percentageLabel.text = "\(Int(percentage * 100))%"
            self.shapeLayer.strokeEnd = percentage
        }

    }

    private func begindDownloadFile(){

        //this fix the bar going back and forth
        shapeLayer.strokeEnd = 0

        let configuration = URLSessionConfiguration.default
        let operationQueue = OperationQueue()
        let urlSession = URLSession(configuration: configuration, delegate: self, delegateQueue: operationQueue)

        guard let url = URL(string: urlString) else { return }
        let downloadTask = urlSession.downloadTask(with: url)



        /****/

        // then lets create your document folder url
        let documentsDirectoryURL =  FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!

        // lets create your destination file url
        let destinationUrl = documentsDirectoryURL.appendingPathComponent(url.lastPathComponent)
        print(destinationUrl)


        // you can use NSURLSession.sharedSession to download the data asynchronously
        URLSession.shared.downloadTask(with: url, completionHandler: { (location, response, error) -> Void in



            guard let location = location, error == nil else { return }
            do {
                // after downloading your file you need to move it to your destination url
                try FileManager.default.moveItem(at: location, to: destinationUrl)
                print("File moved to documents folder")
                print("file has already been downloaded")




                DispatchQueue.main.async {

                    // escondemos label y removemos sublayers (circulo)

                    self.percentageLabel.isHidden = true
                    //self.shapeLayer.removeFromSuperlayer()
                    //self.trackLayer.removeFromSuperlayer()

                    //self.shapeLayer.removeAllAnimations()
                    self.shapeLayer.opacity = 0



                    /************** show pdf ****************/
                    let pdfUrl = destinationUrl.path
                    let rutafile = URL(fileURLWithPath: pdfUrl)
                    print(pdfUrl)
                    if let document = PDFDocument(url: rutafile) {
                        self.pdfView.autoScales = true
                        self.pdfView.document = document
                    }

                    /************** show pdf ****************/


                }


            } catch let error as NSError {
                print(error.localizedDescription)
            }





        }).resume()



        /***/



      downloadTask.resume()





    }

    fileprivate func animateCircle() {
        let basicAnimation = CABasicAnimation(keyPath: "strokeEnd") //animate the shapeLayer.strokeEnd
        basicAnimation.toValue = 1

        basicAnimation.duration = 2


        //need these 2 lines to make the bar stopped at the final point, if not it will be removed upon completion
        basicAnimation.fillMode = kCAFillModeForwards
        basicAnimation.isRemovedOnCompletion = false


        shapeLayer.add(basicAnimation,forKey: "customString")


    }

    @objc private func handleTap(){
        print("animate here")

        //begindDownloadFile()

//        animateCircle()//custom string for forKey value, not sure where will use it later

    }






}

我的问题是我无法隐藏圆圈,我已经在 DispatchQueue.main.async 中尝试使用 self.shapeLayer.removeFromSuperlayer () 但它对我不起作用,使用 self.shapeLayer.opacity = 0

如有任何建议,我将不胜感激

你的 shapeLayer 是红色的,你的 trackLayer 是灰色的。您在图像中显示的是您的 shapeLayer 已删除,但您的 trackLayer 仍然存在,您还需要调用 removeFromSuperlayer。

同时将 trackLayer 的初始声明移出 viewDidLoad() 并将其与 shapeLayer 声明放在一起,以便您可以在该方法之外访问它。即:

let urlString = "https://d0.awsstatic.com/whitepapers/KMS-Cryptographic-Details.pdf"

let shapeLayer = CAShapeLayer()
let trackLayer = CAShapeLayer()