我的 CoreGraphics 代码运行非常缓慢。我怎样才能让这个自定义的 UIScrollView 表现得更好?
My CoreGraphics code is working really slowly. How can I make this custom UIScrollView perform better?
我做了一个自定义 class,它创建了一种可以水平滚动的时间轴。这是我的自定义代码 UIScrollView
:
import UIKit
struct DataPoint {
var fillColor: UIColor = UIColor.grayColor()
init(color: UIColor) {
fillColor = color
}
}
@IBDesignable
class MyView: UIScrollView {
@IBInspectable var lineColor: UIColor = UIColor.grayColor()
@IBInspectable var lineHeight: CGFloat = 65
@IBInspectable var lineWidth: CGFloat = 15
@IBInspectable var lineGap: CGFloat = 25
@IBInspectable var lineCount: Int = 0
var dataPoints = [DataPoint(color: UIColor.greenColor()), DataPoint(color: UIColor.blueColor())]
override init(frame: CGRect) {
super.init(frame: frame)
setupValues()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setupValues()
//fatalError("init(coder:) has not been implemented")
}
func setupValues() {
self.contentSize = CGSize(width: self.frame.width * 2, height: self.frame.height)
self.backgroundColor = UIColor.whiteColor()
self.lineCount = Int(self.frame.width / lineGap)
}
override internal func layoutSubviews() {
super.layoutSubviews()
self.setNeedsDisplay()
self.layoutIfNeeded()
}
override func drawRect(rect: CGRect) {
let ctx = UIGraphicsGetCurrentContext()
CGContextSaveGState(ctx)
for i in 0...lineCount {
let start = CGPoint(x: CGFloat(i) * lineGap, y: self.frame.height)
let end = CGPoint(x: CGFloat(i) * lineGap, y: self.frame.height - lineHeight)
drawLine(from: start, to: end, color: UIColor.grayColor())
if i % (lineCount / (dataPoints.count + 2)) == 0 && i != 0 && i != lineCount {
drawPoint(at: end, radius: 5, color: UIColor.orangeColor())
}
}
CGContextRestoreGState(ctx)
}
func drawLine(from start: CGPoint, to end: CGPoint, color: UIColor) {
let path = UIBezierPath()
path.moveToPoint(start)
path.addLineToPoint(end)
let shapeLayer = CAShapeLayer()
shapeLayer.path = path.CGPath
shapeLayer.strokeColor = color.CGColor
shapeLayer.lineWidth = 1
self.layer.addSublayer(shapeLayer)
}
func drawPoint(at center: CGPoint, radius: CGFloat, color: UIColor) {
let path = UIBezierPath(arcCenter: center, radius: radius, startAngle: CGFloat(0), endAngle: CGFloat(M_PI * 2), clockwise: true)
let shapeLayer = CAShapeLayer()
shapeLayer.path = path.CGPath
shapeLayer.fillColor = color.CGColor
shapeLayer.strokeColor = UIColor.blackColor().CGColor
shapeLayer.lineWidth = 0.5
self.layer.addSublayer(shapeLayer)
}
}
在我的设备和模拟器上,这是非常缓慢和滞后的。我到底做错了什么?我可以采取哪些步骤在滚动时实现稳定的 60fps?
我觉得你每次都在画同样的东西。一切都是静态的...那么为什么不将其全部绘制到图形上下文中并从中制作一个 UIImage 以添加到滚动视图的背景(或前景,取决于您正在做的其他事情)?
您好,我发现了您的问题,您的问题是
override internal func layoutSubviews() {
super.layoutSubviews()
self.setNeedsDisplay()
self.layoutIfNeeded()
}
你不小心进入了一个永无止境的绘画循环
用这个替换这个
override internal func layoutSubviews() {
super.layoutSubviews()
}
或完全删除
我希望这对你有帮助,对我来说效果很好
我做了一个自定义 class,它创建了一种可以水平滚动的时间轴。这是我的自定义代码 UIScrollView
:
import UIKit
struct DataPoint {
var fillColor: UIColor = UIColor.grayColor()
init(color: UIColor) {
fillColor = color
}
}
@IBDesignable
class MyView: UIScrollView {
@IBInspectable var lineColor: UIColor = UIColor.grayColor()
@IBInspectable var lineHeight: CGFloat = 65
@IBInspectable var lineWidth: CGFloat = 15
@IBInspectable var lineGap: CGFloat = 25
@IBInspectable var lineCount: Int = 0
var dataPoints = [DataPoint(color: UIColor.greenColor()), DataPoint(color: UIColor.blueColor())]
override init(frame: CGRect) {
super.init(frame: frame)
setupValues()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setupValues()
//fatalError("init(coder:) has not been implemented")
}
func setupValues() {
self.contentSize = CGSize(width: self.frame.width * 2, height: self.frame.height)
self.backgroundColor = UIColor.whiteColor()
self.lineCount = Int(self.frame.width / lineGap)
}
override internal func layoutSubviews() {
super.layoutSubviews()
self.setNeedsDisplay()
self.layoutIfNeeded()
}
override func drawRect(rect: CGRect) {
let ctx = UIGraphicsGetCurrentContext()
CGContextSaveGState(ctx)
for i in 0...lineCount {
let start = CGPoint(x: CGFloat(i) * lineGap, y: self.frame.height)
let end = CGPoint(x: CGFloat(i) * lineGap, y: self.frame.height - lineHeight)
drawLine(from: start, to: end, color: UIColor.grayColor())
if i % (lineCount / (dataPoints.count + 2)) == 0 && i != 0 && i != lineCount {
drawPoint(at: end, radius: 5, color: UIColor.orangeColor())
}
}
CGContextRestoreGState(ctx)
}
func drawLine(from start: CGPoint, to end: CGPoint, color: UIColor) {
let path = UIBezierPath()
path.moveToPoint(start)
path.addLineToPoint(end)
let shapeLayer = CAShapeLayer()
shapeLayer.path = path.CGPath
shapeLayer.strokeColor = color.CGColor
shapeLayer.lineWidth = 1
self.layer.addSublayer(shapeLayer)
}
func drawPoint(at center: CGPoint, radius: CGFloat, color: UIColor) {
let path = UIBezierPath(arcCenter: center, radius: radius, startAngle: CGFloat(0), endAngle: CGFloat(M_PI * 2), clockwise: true)
let shapeLayer = CAShapeLayer()
shapeLayer.path = path.CGPath
shapeLayer.fillColor = color.CGColor
shapeLayer.strokeColor = UIColor.blackColor().CGColor
shapeLayer.lineWidth = 0.5
self.layer.addSublayer(shapeLayer)
}
}
在我的设备和模拟器上,这是非常缓慢和滞后的。我到底做错了什么?我可以采取哪些步骤在滚动时实现稳定的 60fps?
我觉得你每次都在画同样的东西。一切都是静态的...那么为什么不将其全部绘制到图形上下文中并从中制作一个 UIImage 以添加到滚动视图的背景(或前景,取决于您正在做的其他事情)?
您好,我发现了您的问题,您的问题是
override internal func layoutSubviews() {
super.layoutSubviews()
self.setNeedsDisplay()
self.layoutIfNeeded()
}
你不小心进入了一个永无止境的绘画循环
用这个替换这个
override internal func layoutSubviews() {
super.layoutSubviews()
}
或完全删除
我希望这对你有帮助,对我来说效果很好