You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS触摸绘图开发遇报错:Cannot call value of non-function type `[Float]`求助

Fixing the UIBezierPath Error & Better CGPoint Storage for Your Drawing App

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: guard statements ensure we only attempt to draw when we have enough points

内容的提问来源于stack exchange,提问作者Josef

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:25:02