iOS触摸绘图开发遇报错:Cannot call value of non-function type `[Float]`求助
Hey there! Let's break down what's going wrong and how to fix it, plus a cleaner way to store your touch points for your drawing app.
Why You're Getting That Error
The error Cannot call value of non-function type [Float] pops up because you're trying to access array elements with parentheses pointsX(0) instead of square brackets pointsX[0]. But even fixing that syntax, storing X and Y coordinates in separate arrays is clunky—you have to manually keep both arrays in sync, which is easy to mess up.
Better Solution: Use a Single [CGPoint] Array
Instead of two separate arrays for X and Y values, store your touch points directly as CGPoint instances in one array. This keeps your coordinates paired correctly, simplifies working with UIBezierPath, and makes your code more intuitive.
Modified Code Example
First, replace your existing pointsX and pointsY arrays with a single array for CGPoint:
var touchPoints: [CGPoint] = [] var touchIndicators: [UIView] = [] var draw = true // Assuming this is your drawing mode toggle
Update your touchesBegan method to store full CGPoint values instead of splitting coordinates:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { guard draw else { return } for touch in touches { let location = touch.location(in: view) touchPoints.append(location) // Store the complete touch point // Add your touch indicator view (unchanged from your original code) let touchIndicator = UIView(frame: CGRect(x: location.x - 10, y: location.y - 10, width: 20, height: 20)) touchIndicator.alpha = 0.8 touchIndicator.backgroundColor = .red touchIndicator.layer.cornerRadius = 10 view.addSubview(touchIndicator) touchIndicators.append(touchIndicator) // Trigger drawing once we have 2 or more points if touchPoints.count >= 2 { drawFilledShape() } } }
Add a helper method to dynamically create and render the filled shape using your touchPoints array:
func drawFilledShape() { guard touchPoints.count >= 2 else { return } // Build the bezier path from your collected touch points let shapePath = UIBezierPath() shapePath.move(to: touchPoints[0]) // Start at the first touch point // Add lines to every subsequent point for point in touchPoints.dropFirst() { shapePath.addLine(to: point) } shapePath.close() // Close the path to form a closed, fillable shape // Create a shape layer to render the path let shapeLayer = CAShapeLayer() shapeLayer.path = shapePath.cgPath shapeLayer.fillColor = UIColor.red.cgColor shapeLayer.strokeColor = UIColor.black.cgColor // Optional: add a border shapeLayer.lineWidth = 2 // Optional: adjust border thickness // Add the layer to your view's layer hierarchy view.layer.addSublayer(shapeLayer) }
Key Improvements
- No more coordinate sync errors: each touch point is stored as a single, unified
CGPoint - Dynamic shape building: the helper method automatically uses all collected points to form the shape
- Cleaner code structure: separating drawing logic into a helper method makes it easier to update or extend later
- Safety checks:
guardstatements ensure we only attempt to draw when we have enough points
内容的提问来源于stack exchange,提问作者Josef

