我创建了一个UIView的调用,我在其中绘制了一个图形。我正在尝试传递新数据并将其更新。
当我在模拟器上运行应用程序并单击视图所在的控制器所在的选项卡时,我收到此错误:
线程1:EXC_BAD_INSTRUCTION(代码= EXC_1386_INVOP,子代码= 0x0)
在这一行:
let maxValue = graphPoints.maxElement()
以下是我的视图代码:
@IBDesignable class GraphView: UIView {
var graphPoints :[Int]!
override init(frame: CGRect) {
super.init(frame: frame)
}
init(graphPoints: [Int]) {
self.graphPoints = graphPoints
super.init(frame: CGRectZero)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
@IBInspectable var startColor: UIColor = UIColor.redColor()
@IBInspectable var endColor: UIColor = UIColor.greenColor()
override func drawRect(rect: CGRect) {
let width = rect.width
let height = rect.height
//set up background clipping area
let path = UIBezierPath(roundedRect: rect,
byRoundingCorners: UIRectCorner.AllCorners,
cornerRadii: CGSize(width: 8.0, height: 8.0))
path.addClip()
//2 - get the current context
let context = UIGraphicsGetCurrentContext()
let colors = [startColor.CGColor, endColor.CGColor]
//3 - set up the color space
let colorSpace = CGColorSpaceCreateDeviceRGB()
//4 - set up the color stops
let colorLocations:[CGFloat] = [0.0, 1.0]
//5 - create the gradient
let gradient = CGGradientCreateWithColors(colorSpace,
colors,
colorLocations)
//6 - draw the gradient
var startPoint = CGPoint.zeroPoint
var endPoint = CGPoint(x:0, y:self.bounds.height)
CGContextDrawLinearGradient(context,
gradient,
startPoint,
endPoint,
.DrawsBeforeStartLocation)
//calculate the x point
let rightMargin:CGFloat = 40
let leftMargin : CGFloat = 10
let columnXPoint = { (column:Int) -> CGFloat in
//Calculate gap between points
let spacer = (width - rightMargin - leftMargin - 4) /
CGFloat((self.graphPoints.count - 1))
var x:CGFloat = CGFloat(column) * spacer
x += leftMargin + 2
print(x)
return x
}
// calculate the y point
let topBorder:CGFloat = 30
let bottomBorder:CGFloat = 50
let graphHeight = height - topBorder - bottomBorder
let maxValue = graphPoints.maxElement()
let columnYPoint = { (graphPoint:Int) -> CGFloat in
var y:CGFloat = CGFloat(graphPoint) /
CGFloat(maxValue!) * graphHeight
y = graphHeight + topBorder - y // Flip the graph
print(y)
return y
}
// draw the line graph
UIColor.whiteColor().setFill()
UIColor.whiteColor().setStroke()
//set up the points line
let graphPath = UIBezierPath()
//go to start of line
graphPath.moveToPoint(CGPoint(x:columnXPoint(0), y:columnYPoint(graphPoints[0])))
//add points for each item in the graphPoints array
//at the correct (x, y) for the point
for i in 1..<graphPoints.count {
let nextPoint = CGPoint(x:columnXPoint(i),
y:columnYPoint(graphPoints[i]))
graphPath.addLineToPoint(nextPoint)
}
//Create the clipping path for the graph gradient
//1 - save the state of the context (commented out for now)
CGContextSaveGState(context)
//2 - make a copy of the path
let clippingPath = graphPath.copy() as! UIBezierPath
//3 - add lines to the copied path to complete the clip area
clippingPath.addLineToPoint(CGPoint(
x: columnXPoint(graphPoints.count - 1),
y:height))
clippingPath.addLineToPoint(CGPoint(
x:columnXPoint(0),
y:height))
clippingPath.closePath()
//4 - add the clipping path to the context
clippingPath.addClip()
let highestYPoint = columnYPoint(maxValue!)
startPoint = CGPoint(x:leftMargin, y: highestYPoint)
endPoint = CGPoint(x:rightMargin, y:self.bounds.height)
CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, .DrawsBeforeStartLocation)
CGContextRestoreGState(context)
//draw the line on top of the clipped gradient
graphPath.lineWidth = 2.0
graphPath.stroke()
//Draw the circles on top of graph stroke
for i in 0..<graphPoints.count {
var point = CGPoint(x:columnXPoint(i), y:columnYPoint(graphPoints[i]))
point.x -= 5.0/2
point.y -= 5.0/2
let circle = UIBezierPath(ovalInRect:
CGRect(origin: point,
size: CGSize(width: 5.0, height: 5.0)))
circle.fill()
}
//Draw horizontal graph lines on the top of everything
let linePath = UIBezierPath()
//top line
linePath.moveToPoint(CGPoint(x:leftMargin, y: topBorder))
linePath.addLineToPoint(CGPoint(x: width - rightMargin,
y:topBorder))
//center line
linePath.moveToPoint(CGPoint(x:leftMargin,
y: graphHeight/2 + topBorder))
linePath.addLineToPoint(CGPoint(x:width - rightMargin,
y:graphHeight/2 + topBorder))
//bottom line
linePath.moveToPoint(CGPoint(x:leftMargin,
y:height - bottomBorder))
linePath.addLineToPoint(CGPoint(x:width - rightMargin,
y:height - bottomBorder))
let color = UIColor(white: 1.0, alpha: 0.3)
color.setStroke()
linePath.lineWidth = 1.0
linePath.stroke()
}
这是我的视图控制器的代码,我将数据传递给视图。
import UIKit
import QuartzCore
class ProgressViewController: UIViewController {
@IBOutlet weak var graphView: UIView!
var firstGraph : GraphView!
override func viewDidLoad() {
self.graphView = self.firstGraph
self.firstGraph = GraphView(graphPoints: [2240, 1983, 2171, 2017, 1842, 1992, 2347])
我是Swift的新手,在寻找答案之后,我对这个问题感到难过。任何帮助表示赞赏。