检测 UITextView 上的点击仅检测取消

Detecting tap on a UITextView only detects cancellations

我一直在努力检测使用 Swift 的 UITextView 上的点击。

我的 UITextViews 在 table 中,我必须能够检测到 links 并按下它们,那些 links 的长度是未知的。

此外,如果我点击单元格,我没有点击 link,我想在我的导航控制器堆栈上推送一个新的 UIViewController。

我试图创建自己的文本视图来覆盖 touchesCancelled,但没有成功。它检测到不被视为在真实设备上点击的取消。

这个bug在模拟器上没有出现,但是在真机上好像不能点击,只能长按才可以。

class LinkTextView: UITextView {
    override func touchesCancelled(touches: Set<NSObject>!, withEvent event: UIEvent!) {
         self.textViewWasTapped(self) 
    }
}

我尝试直接添加手势识别器。我在那里也没有取得任何成功。它根本不调用手势识别器。

我将 UIGestureReconizer 委托添加到我的 UIViewController 和

中的那些行
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
     var singleTap : UIGestureRecognizer = UIGestureRecognizer(target: self, action: "tapTextView:")
        singleTap.delegate = self
             cell.mTextOutlet.attributedText = myMutableString
             cell.mTextOutlet.addGestureRecognizer(singleTap) 

在我的 LinkTextView 中 class :

class LinkTextView: UITextView {
    func tapTextView(stapGesture: UIGestureRecognizer){
        println("TAPPING1")
    }
}

我查看了论坛,发现了这个 post:post. It suggests to use CHHLinkTextView。我尝试使用它,但我想要的是自动检测 link ,正常的 uitextview 实际上是这样做的。

我曾尝试使用界面生成器中的复选框来使用 CHHLinkTextView 解析 links,但它不起作用。我在文档中没有看到任何建议可以完成的内容。

我应该如何进行?

您的子类化 UITextView 的第一次尝试已经非常接近了,但与其仅覆盖 touchesCancelled,您还需要覆盖所有 touches* 方法,即

  • touchesBegan
  • touchesMoved
  • touchesEnded
  • touchesCancelled

在覆盖的方法中,通过获取 textView 的 nextResponder() 将触摸发送到响应链,检查它不是 nil,然后在下一个响应者上调用该方法。

之所以可行,是因为 UITextView 会拦截 URL 上的触摸,而 UIResponder 方法将永远不会被调用——通过实现自己尝试textView:shouldInteractWithURL:inRange 在您的 tableViewCell 或任何地方,您会看到它在传递任何触摸事件之前被调用。

这应该是您要尝试执行的操作的最低要求(重复但很短):

class PassThroughTextView: UITextView {

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        if let next = next {
            next.touchesBegan(touches, with: event)
        } else {
            super.touchesBegan(touches, with: event)
        }
    }

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        if let next = next {
            next.touchesEnded(touches, with: event)
        } else {
            super.touchesEnded(touches, with: event)
        }
    }

    override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
        if let next = next {
            next.touchesCancelled(touches, with: event)
        } else {
            super.touchesCancelled(touches, with: event)
        }
    }

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        if let next = next {
            next.touchesMoved(touches, with: event)
        } else {
            super.touchesMoved(touches, with: event)
        }
    }
}

// In case you want to do anything with the URL or textView in your tableViewCell...
class TableViewCell: UITableViewCell, UITextViewDelegate {
    @IBOutlet var textView: PassThroughTextView!

    func textView(textView: UITextView, shouldInteractWithURL URL: NSURL, inRange characterRange: NSRange) -> Bool {
        println("textView shouldInteractWithURL")
        return true
    }

}

我按照 Ralfonso 所说的做了,但没有成功,但它帮助我意识到我遇到了手势识别器冲突。原来我不必重写 UITextView 的所有 4 个方法,我只是重写了 touchesBegan。 我在 viewDidLoad 中所做的是添加一个手势识别器来关闭键盘:

      var tapOutTextField: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "dismissKeyboard")
      self.view.addGestureRecognizer(tapOutTextField)

没有意义并让我误入歧途的是 touchesBegan 实际上是在延迟后调用的(touchCancelled 也是如此),我无法获得与 UIButton 相同的行为。这一切都是因为这个手势识别器冲突。