iOS:无法检测到CALayer边界之外的触摸

iOS:无法检测到CALayer边界之外的触摸,ios,swift,cocoa-touch,frame,calayer,Ios,Swift,Cocoa Touch,Frame,Calayer,我正在创建一个可重用的多状态开关,它从UIControl扩展而来,看起来类似于默认的UISwitch,具有两个以上的状态。该实现类似于为每个状态添加Calayer和一个附加层,用于在UIView上高亮显示选定状态 用户界面如下所示 问题是,当用户点击方格边框的正外侧时,我无法识别状态的触摸,如图所示。我添加了一个简单方便的方法(getIndexForLocation)来返回给定接触点的选定状态的索引。使用返回的选定索引,我将突出显示指示器的位置移动到选定状态的中心 func getIndexF

我正在创建一个可重用的多状态开关,它从UIControl扩展而来,看起来类似于默认的UISwitch,具有两个以上的状态。该实现类似于为每个状态添加Calayer和一个附加层,用于在UIView上高亮显示选定状态

用户界面如下所示

问题是,当用户点击方格边框的正外侧时,我无法识别状态的触摸,如图所示。我添加了一个简单方便的方法(getIndexForLocation)来返回给定接触点的选定状态的索引。使用返回的选定索引,我将突出显示指示器的位置移动到选定状态的中心

func getIndexForLocation(_ point: CGPoint) -> Int {
    var index = selectedIndex
    let sLayers = self.controlLayer.sublayers
    for i in 0..<totalStates {
        if sLayers![i].frame.contains(point) {
            index = i
        }
    }
    return index
}

任何帮助都将不胜感激。

您正在通过说
如果杀戮者![i] .frame.contains(点)
。因此,最简单的解决方案是使每个“按钮”的框架大得多——大到足以覆盖您希望作为该“按钮”触摸的整个区域。请记住,即使框架很大,图形也可以很小

另外,顺便说一下,您的代码很愚蠢,因为您基本上是在执行命中测试。层的命中测试是内置的,所以一旦你有了正确的帧,你所要做的就是调用superlayer。这将告诉你哪一层被点击

(当然,使用子视图而不是图层会更好。视图可以检测触摸,而图层则不能。)

func performSwitch(to index: Int) -> () {
    guard selectedIndex != index else {
        return
    }

    let offsetDiff = CGFloat((index - selectedIndex) * (stateSize + 2))
    let oldPosition = indicatorPosition
    indicatorPosition.x += offsetDiff
    let newPosition = indicatorPosition

    let animation: CABasicAnimation = CABasicAnimation(keyPath: "position")
    animation.timingFunction = CAMediaTimingFunction(controlPoints: 0.785, 0.135, 0.15, 0.86)
    animation.duration = 0.6
    animation.fromValue = NSValue(cgPoint: oldPosition!)
    animation.toValue = NSValue(cgPoint: newPosition!)
    animation.autoreverses = false
    animation.delegate = self
    animation.isRemovedOnCompletion = false
    animation.fillMode = kCAFillModeForwards


    self.selectedIndex = index
    self.stateIndicator.add(animation, forKey: "position")
}