- 小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
最后需要完成的效果:
一般来说,进度条是用来监听下载进度的,接下来需要模拟下载文件的过程,并且让进度条根据下载进度发生相应的改变。 创建一个方法来下载文件,这里使用URLSession以方便观察下载的情况。这里需要遵守URLSessionDownloadDelegate,并实现代理方法,否则会报错。
func beginDownloadingFile() {
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)
downloadTask.resume()
}
复制代码
接下来在URLSession的代理方法中,根据已经写的data和总共需要写的data计算出百分比,然后根据得出的百分比改变shapeLayer的strokeEnd。这里改变strokeEnd的时候需要放在主线程,否则视图不会发生改变。
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
let percentage = CGFloat(totalBytesWritten) / CGFloat(totalBytesExpectedToWrite)
DispatchQueue.main.async {
self.shapeLayer.strokeEnd = percentage
}
print(percentage)
}
复制代码
接下来需要创建一个label放在shapelayer的中间进行显示。 创建一个UILabel让VC持有,文字为Start,文字居中对齐,字体大小为加粗32号,字体颜色为黑色。
let percentageLabel: UILabel = {
let label = UILabel()
label.text = "Start"
label.textAlignment = .center
label.font = UIFont.boldSystemFont(ofSize: 32)
label.textColor = .black
return label
}()
复制代码
在视图中添加percentageLabel为视图的子view,设置好label的frame,并将其放在视图中心。
view.addSubview(percentageLabel)
percentageLabel.frame = CGRect(x: 0, y: 0, width: 100, height: 100)
percentageLabel.center = view.center
复制代码
接下来需要在下载任务开始时,将percentageLabel的文字改为对应的百分比。 这个就在刚才URLSession的代理方法里面设置strokeEnd的地方设置percentageLabel的text就好了。这里注意设置text也需要在主线程里面。
DispatchQueue.main.async {
self.percentageLabel.text = "\(Int(percentage * 100))%"
self.shapeLayer.strokeEnd = percentage
}
复制代码
到这里进度条就会跟着下载的进度前进,并且在中间显示白分比了。
完整代码:
import UIKit
class ViewController: UIViewController,URLSessionDownloadDelegate {
let shapeLayer = CAShapeLayer()
let percentageLabel: UILabel = {
let label = UILabel()
label.text = "Start"
label.textAlignment = .center
label.font = UIFont.boldSystemFont(ofSize: 32)
label.textColor = .black
return label
}()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
view.addSubview(percentageLabel)
percentageLabel.frame = CGRect(x: 0, y: 0, width: 100, height: 100)
percentageLabel.center = view.center
let circularPath = UIBezierPath(arcCenter: .zero, radius: 100, startAngle: 0, endAngle: CGFloat.pi * 2, clockwise: true)
let trackLayer = CAShapeLayer()
trackLayer.path = circularPath.cgPath
trackLayer.strokeColor = UIColor.lightGray.cgColor
trackLayer.lineWidth = 10
trackLayer.position = view.center
trackLayer.fillColor = UIColor.clear.cgColor
trackLayer.lineCap = .round
view.layer.addSublayer(trackLayer)
shapeLayer.path = circularPath.cgPath
shapeLayer.strokeEnd = 0
shapeLayer.position = view.center
shapeLayer.strokeColor = UIColor.red.cgColor
shapeLayer.lineWidth = 10
shapeLayer.fillColor = UIColor.clear.cgColor
shapeLayer.lineCap = .round
shapeLayer.transform = CATransform3DMakeRotation(-CGFloat.pi / 2, 0, 0, 1)
view.layer.addSublayer(shapeLayer)
view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleTap)))
}
let urlString = "https://firebasestorage.googleapis.com/v0/b/firestorechat-e64ac.appspot.com/o/intermediate_training_rec.mp4?alt=media&token=e20261d0-7219-49d2-b32d-367e1606500c"
func beginDownloadingFile() {
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)
downloadTask.resume()
}
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
}
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
let percentage = CGFloat(totalBytesWritten) / CGFloat(totalBytesExpectedToWrite)
DispatchQueue.main.async {
self.percentageLabel.text = "\(Int(percentage * 100))%"
self.shapeLayer.strokeEnd = percentage
}
print(percentage)
}
@objc func handleTap() {
beginDownloadingFile()
// let basicAnimation = CABasicAnimation(keyPath: "strokeEnd")
// basicAnimation.toValue = 1
// basicAnimation.duration = 2
// basicAnimation.fillMode = .forwards
// basicAnimation.isRemovedOnCompletion = false
// shapeLayer.add(basicAnimation, forKey: "stokeAnimation")
}
}
复制代码