在UITableViewCell中检测UITextView中的数据 [英] Detect Data in UITextView in UITableViewCell
问题描述
我在 UITableViewCell
子类中有一个 UITextView
。它有可编辑
和 userInteractionEnabled
都设置为否
。这允许 UITextView
检测链接和电话号码等数据。正确检测数据,但由于禁用了userInteraction,因此无法响应该数据的点击。如果我将 userInteractionEnabled
设置为 YES
,它可以正常工作,但是 UITableViewCell $由于UITextView吞下了触摸,因此无法选择c $ c>。
如果用户点击它,我想关注该链接,但我希望 didSelectRowAtIndexPath:
to如果点击基本文本,则调用。
我认为正确的方法是子类 UITextView
并将触摸传递给单元格,但我似乎找不到检测点击是否在链接上的方法。
这是一个类似的问题,但答案只是将所有接触传递给细胞。我想只传递触摸,如果它们不在一块检测到的数据上。
2。使用 point(inside:with :)
作为覆盖 hitTest(_的替代方法) :with:)
,您可以使用 点(内:其中:)
。 point(inside:with :)
具有以下声明:
func point(内部点:CGPoint,事件:UIEvent?) - > Bool
返回一个布尔值,指示接收器是否包含指定的点。
以下代码显示了如何实现点(内部) :在
而不是 UITextView
子类中使用:) hitTest(_:with :)
:
LinkTextView.swift
import UIKit
class LinkTextView:UITextView {
覆盖init(frame:CGRect,textContainer:NSTextContainer?){
super.init(frame:frame,textContainer: textContainer)
configure()
}
必需init?(编码器aDecoder:NSCoder){
super.init(编码器:aDecoder)
configure( )
}
func configure(){
isScrollEnabled = false
isEditable = false
isUserInteractionEnabled = true
isSelectable = true
dat aDetectorTypes = .link
}
覆盖func point(内部点:CGPoint,事件:UIEvent?) - > Bool {
//从抽头位置获取字符索引
let characterIndex = layoutManager.characterIndex(for:point,in:textContainer,fractionOfDistanceBetweenInsertionPoints:nil)
// if我们检测到一个链接,通过返回true来处理tap ...
if let _ = textStorage.attribute(NSLinkAttributeName,at:characterIndex,effectiveRange:nil){
return true
}
// ...否则返回false;点击将继续下一个接收者
返回false
}
}
这个GitHub仓库上有完整的项目: LinkTextViewCell 。
您可以在<$ c $内了解有关管理 UITextView
的更多信息c> UITableViewCell 阅读使用单元格中的链接处理UITextView的快速方法。
您可以了解有关之间区别的更多信息hitTest(_:with :)
和指向(内部:带:):
通过阅读Apple的指南和示例代码:事件传递:响应者链。
I have a UITextView
inside a UITableViewCell
subclass. It has editable
and userInteractionEnabled
both set to NO
. This allows the UITextView
to detect data such as links and phone numbers. The data is detected correctly, but because userInteraction is disabled, it cannot respond to taps on that data. If I set userInteractionEnabled
to YES
, it works fine, but then the UITableViewCell
cannot be selected since the UITextView swallows the touch.
I want to follow the link if the user taps on it, but I want didSelectRowAtIndexPath:
to be called if the tap is on basic text.
I think the right approach is to subclass UITextView
and pass touches to the cell, but I can't seem to find a way to detect whether or not the tap was on a link.
This is a similar question, but the answer will just pass all touches to the cell. I want to only pass the touches if they are NOT on a piece of detected data. issue enabling dataDetectorTypes on a UITextView in a UITableViewCell
1. Using hitTest(_:with:)
UIView
has a method called hitTest(_:with:)
that has the following definition:
func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView?
Returns the farthest descendant of the receiver in the view hierarchy (including itself) that contains a specified point.
UITextView
being a subclass of UIView
, you can implement this method in any subclass of UITextView
you may want to create.
The following Swift 3 example shows a UITableViewController
that contains a single static UITableViewCell
. The UITableViewCell
embeds a UITextView
. Any tap on a link inside the UITextView
will launch Safari app; any tap on basic text inside the UITextView
will trigger a push segue to the following UIViewController
.
LinkTextView.swift
import UIKit
class LinkTextView: UITextView {
override init(frame: CGRect, textContainer: NSTextContainer?) {
super.init(frame: frame, textContainer: textContainer)
configure()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
configure()
}
func configure() {
isScrollEnabled = false
isEditable = false
isUserInteractionEnabled = true
isSelectable = true
dataDetectorTypes = .link
}
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
// Get the character index from the tap location
let characterIndex = layoutManager.characterIndex(for: point, in: textContainer, fractionOfDistanceBetweenInsertionPoints: nil)
// if we detect a link, handle the tap by returning self...
if let _ = textStorage.attribute(NSLinkAttributeName, at: characterIndex, effectiveRange: nil) {
return self
}
// ... otherwise return nil ; the tap will go on to the next receiver
return nil
}
}
TextViewCell.swift
import UIKit
class TextViewCell: UITableViewCell {
@IBOutlet weak var textView: LinkTextView!
}
TableViewController.swift
import UIKit
class TableViewController: UITableViewController {
@IBOutlet weak var cell: TextViewCell!
override func viewDidLoad() {
super.viewDidLoad()
// Add text to cell's textView
let text = "http://www.google.com Lorem ipsum dolor sit amet, consectetur adipiscing elit, http://www.yahoo.com sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
cell.textView.text = text
}
}
2. Using point(inside:with:)
As an alternative to override hitTest(_:with:)
, you can use point(inside:with:)
. point(inside:with:)
has the following declaration:
func point(inside point: CGPoint, with event: UIEvent?) -> Bool
Returns a Boolean value indicating whether the receiver contains the specified point.
The following code shows how to implement point(inside:with:)
instead of hitTest(_:with:)
in your UITextView
subclass:
LinkTextView.swift
import UIKit
class LinkTextView: UITextView {
override init(frame: CGRect, textContainer: NSTextContainer?) {
super.init(frame: frame, textContainer: textContainer)
configure()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
configure()
}
func configure() {
isScrollEnabled = false
isEditable = false
isUserInteractionEnabled = true
isSelectable = true
dataDetectorTypes = .link
}
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
// Get the character index from the tap location
let characterIndex = layoutManager.characterIndex(for: point, in: textContainer, fractionOfDistanceBetweenInsertionPoints: nil)
// if we detect a link, handle the tap by returning true...
if let _ = textStorage.attribute(NSLinkAttributeName, at: characterIndex, effectiveRange: nil) {
return true
}
// ... otherwise return false ; the tap will go on to the next receiver
return false
}
}
The complete project is available on this GitHub repo: LinkTextViewCell.
You can learn more about managing a UITextView
inside a UITableViewCell
by reading Swifty Approach to Handling UITextViews With Links in Cells.
You can learn more about the difference between hitTest(_:with:)
and point(inside:with:)
by reading Apple's Guide and Sample Code: "Event Delivery: The Responder Chain".
这篇关于在UITableViewCell中检测UITextView中的数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!