Data discovery in UITextView in UITableViewCell

I have a UITextViewsubclass inside UITableViewCell. It has editable, and userInteractionEnabledboth are set to NO. This allows you to UITextViewdetect data such as links and phone numbers. The data was detected correctly, but since userInteraction is disabled, it cannot respond to clicking on this data. If I set userInteractionEnabledto YES, it works fine, but then UITableViewCellcannot be selected, since the UITextView swallows the touch.

I want to follow the link if the user clicks on it, but I want it to be didSelectRowAtIndexPath:called if it is brief in the main text.

I think the correct approach is to subclass UITextViewand pass touches to the cell, but I cannot find a way to determine if there was an answer to the link.

This is a similar question, but the answer will just pass all the touches to the cell. I only want to pass strokes if they are NOT on the part of the detected data. return data DataDetectorTypes in UITextView in UITableViewCell

+4
source share
2 answers

1. Using hitTest(_:with:)

UIViewhas a method hitTest(_:with:)that has the following definition:

func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView?

Returns the farthest descendant of the recipient in the view hierarchy (including itself) that contains the specified point.

UITextView UIView, UITextView, .


Swift 3 UITableViewController, UITableViewCell. UITableViewCell UITextView. UITextView Safari; UITextView 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 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
    }

}

enter image description here


2. point(inside:with:)

hitTest(_:with:) point(inside:with:). point(inside:with:) :

func point(inside point: CGPoint, with event: UIEvent?) -> Bool

, , .


, point(inside:with:) hitTest(_:with:) UITextView:

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
    }

}

GitHub: LinkTextViewCell.

UITextView UITableViewCell, Swifty Approach UITextViews .

hitTest(_:with:) point(inside:with:), Apple : " : " .

+7

. UITextView :

@protocol SOTextViewDelegate;

@interface SOTextView : UITextView

@property (nonatomic, weak) id<SOTextViewDelegate> soDelegate;

@end

@protocol SOTextViewDelegate <NSObject>
@optional
- (void)soTextViewWasTapped:(SOTextView *)soTextview;

@end

:

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {

    if (self.selectedRange.length == 0 &&
        [_soDelegate respondsToSelector:@selector(soTextViewWasTapped:)]))

        [_soDelegate soTextViewWasTapped:self];
}

, textView . , .

, , textView , , .

+3

All Articles