Swift 3 个手势识别器 path.boundingBox 是无限的

Swift 3 Gesture Recognizers path.boundingBox is infinite

我想了解有关自定义手势识别器的更多信息,所以我正在阅读 Ray Wenderlich 教程,我计划修改该教程以了解详细信息以及我可以轻松更改的内容以了解每个部分的工作原理,但它是用 Swift 的早期版本编写。 Swift 更新了大部分代码,我能够手动修复其余部分,除了我无法在屏幕上绘制触摸手势,而且没有任何形状被识别为圆圈,我希望这两个回到同样的问题。网址及代码片段如下:

https://www.raywenderlich.com/104744/uigesturerecognizer-tutorial-creating-custom-recognizers

import UIKit
import UIKit.UIGestureRecognizerSubclass

class CircleGestureRecognizer: UIGestureRecognizer {

fileprivate var touchedPoints = [CGPoint]() // point history
var fitResult = CircleResult() // information about how circle-like is the path
var tolerance: CGFloat = 0.2 // circle wiggle room, lower is more circle like higher is oval or other
var isCircle = false
var path = CGMutablePath() // running CGPath - helps with drawing

override func touchesBegan(_ touches: (Set<UITouch>!), with event: UIEvent) {

if touches.count != 1 {
  state = .failed
}
state = .began

let window = view?.window
if let touches = touches, let loc = touches.first?.location(in: window) {
    //print("path 1 \(path.currentPoint)")
  path.move(to: CGPoint(x: loc.x, y: loc.y)) // start the path
    print("path 2 \(path.currentPoint)")
}
//super.touchesBegan(touches, with: event)
}

override func touchesMoved(_ touches: (Set<UITouch>!), with event: UIEvent) {

    // 1
    if state == .failed {
        return
    }

    // 2
    let window = view?.window
    if let touches = touches, let loc = touches.first?.location(in: window) {
        // 3
        touchedPoints.append(loc)

        print("path 3 \(path.currentPoint)")
        path.move(to: CGPoint(x: loc.x, y: loc.y))
        print("path 4 \(path.currentPoint)")

        // 4
        state = .changed
    }
}

override func touchesEnded(_ touches: (Set<UITouch>!), with event: UIEvent) {

    print("path 5 \(path.currentPoint)")
// now that the user has stopped touching, figure out if the path was a circle
fitResult = fitCircle(touchedPoints)

// make sure there are no points in the middle of the circle
    let hasInside = anyPointsInTheMiddle()

    let percentOverlap = calculateBoundingOverlap()

    isCircle = fitResult.error <= tolerance && !hasInside && percentOverlap > (1-tolerance)

state = isCircle ? .ended : .failed
}

override func reset() {
//super.reset()
touchedPoints.removeAll(keepingCapacity: true)
path = CGMutablePath()
isCircle = false
state = .possible
}

fileprivate func anyPointsInTheMiddle() -> Bool {
    // 1
    let fitInnerRadius = fitResult.radius / sqrt(2) * tolerance
    // 2
    let innerBox = CGRect(
        x: fitResult.center.x - fitInnerRadius,
        y: fitResult.center.y - fitInnerRadius,
        width: 2 * fitInnerRadius,
        height: 2 * fitInnerRadius)

    // 3
    var hasInside = false
    for point in touchedPoints {
        if innerBox.contains(point) {
            hasInside = true
            break
        }
    }

    //print(hasInside)
    return hasInside
}

fileprivate func calculateBoundingOverlap() -> CGFloat {
    // 1
    let fitBoundingBox = CGRect(
        x: fitResult.center.x - fitResult.radius,
        y: fitResult.center.y - fitResult.radius,
        width: 2 * fitResult.radius,
        height: 2 * fitResult.radius)
    let pathBoundingBox = path.boundingBox

    // 2
    let overlapRect = fitBoundingBox.intersection(pathBoundingBox)

    // 3
    let overlapRectArea = overlapRect.width * overlapRect.height
    let circleBoxArea = fitBoundingBox.height * fitBoundingBox.width

    let percentOverlap = overlapRectArea / circleBoxArea
    print("Percent Overlap \(percentOverlap)")
    print("pathBoundingBox \(pathBoundingBox)")
    print("path 6 \(path.currentPoint)")

    return percentOverlap
}

override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent) {
state = .cancelled // forward the cancel state
}
}

如教程中所示,这段代码应该将路径的边界框与适合圆形的框进行比较并比较重叠,但是当我打印 pathBoundingBox 时状态为:"pathBoundingBox (inf, inf, 0.0, 0.0)" 这可能是 percentOverlap 为 0 的原因。我认为它是 path.move(to: loc),其中 loc 是第一个触摸位置,但 move(to:) 的文档说 "This method implicitly ends the current subpath (if any) and sets the current point to the value in the point parameter." 所以我我正在努力弄清楚为什么 path.boundingBox 是无限的...

这不是无限边界框,它恰恰相反 — 零边界框。问题是您的 path 是空的。