UITextView链接点击识别被延迟

时间:2014-03-13 13:06:00

标签: ios objective-c uitextview

在iOS 7应用中,我有一个UITextView,其中包含一个链接,但点击该链接不会触发。它只响应尴尬的“轻拍”。我希望它在用户点击它时立即响应,例如UIWebView链接点按的工作方式。这是我的设置:

- (void)viewDidLoad
{
    [super viewDidLoad];

    NSMutableAttributedString *text = [[NSMutableAttributedString alloc] initWithString:@"Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."];
    [text addAttribute:NSLinkAttributeName value:@"myurl://tapped" range:NSMakeRange(6, 16)];

    self.textView.attributedText = text;
    self.textView.editable = NO;
    self.textView.delaysContentTouches = NO;
}

- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange
{
    if ([[URL scheme] isEqualToString:@"myurl"])
    {
        // Handle tap

        return NO;
    }

    return YES;
}

shouldInteractWithURL方法的Apple文档说明:“如果用户点击或长按URL链接,文本视图会调用此方法”。长按工作正常,但水龙头似乎不起作用。

是否有人知道如何立即做出回应?

8 个答案:

答案 0 :(得分:35)

如果您仍想使用原生UITextView,则可以在文本视图中添加点按识别器,并在点击位置获取字符串属性。当您找到链接时,可以立即打开它。

我为iOS 7/8写了一个解决这个问题的要点。它是UITextView的轻量级扩展,也可以转发-[UITextViewDelegate textView:shouldInteractWithURL:inRange:]并公开内部点击手势识别器。

https://gist.github.com/benjaminbojko/c92ac19fe4db3302bd28

以下是一个简单示例:以下示例仅适用于iOS 8.请参阅上面的要点以获得iOS 7 + 8支持。

添加点击识别器:

// ...

UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tappedTextView:)];
[myTextView addGestureRecognizer:tapRecognizer];
myTextView.selectable = YES; // otherwise the gesture won't recognize

// ...

添加你的回调:

- (void)tappedTextView:(UITapGestureRecognizer *)tapGesture {
    if (tapGesture.state != UIGestureRecognizerStateEnded) {
        return;
    }

    UITextView *textView = (UITextView *)tapGesture.view;
    CGPoint tapLocation = [tapGesture locationInView:textView];
    UITextPosition *textPosition = [textView closestPositionToPoint:tapLocation];
    NSDictionary *attributes = [textView textStylingAtPosition:textPosition inDirection:UITextStorageDirectionForward];

    NSURL *url = attributes[NSLinkAttributeName];

    if (url) {
        [[UIApplication sharedApplication] openURL:url];
    }
}

快速版:

点按识别器:

let tapRecognizer = UITapGestureRecognizer(target: self, action: Selector("tappedTextView:"))
myTextView.addGestureRecognizer(tapRecognizer)
myTextView.selectable = true

回调:

func tappedTextView(tapGesture: UIGestureRecognizer) {

        let textView = tapGesture.view as! UITextView
        let tapLocation = tapGesture.locationInView(textView)
        let textPosition = textView.closestPositionToPoint(tapLocation)
        let attr: NSDictionary = textView.textStylingAtPosition(textPosition, inDirection: UITextStorageDirection.Forward)

        if let url: NSURL = attr[NSLinkAttributeName] as? NSURL {
            UIApplication.sharedApplication().openURL(url)
        }

        }

答案 1 :(得分:14)

UITextView是否可以选择?试试:

self.textView.selectable = YES;

编辑:

我开始认为,与苹果公司所说的相反,长按可能是解决问题的唯一途径。检查此link,也许会有所帮助。

答案 2 :(得分:7)

正如nnarayann所说,CCHLinkTextView避免了延迟点击识别的问题。该库实现了自己的手势识别器,现在可以在1.0版本中使用。

答案 3 :(得分:3)

Swift 4 解决方案

  • 使用点击手势识别器处理链接
  • isSelectabletrue还是false,是否可行
let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleLinkTap(_:)))
textView.addGestureRecognizer(tapRecognizer)

@objc func handleLinkTap(_ recognizer: UITapGestureRecognizer) {
    let tapLocation = recognizer.location(in: textView)
    guard
        let textPosition = textView.closestPosition(to: tapLocation),
        let url = textView.textStyling(at: textPosition, in: .forward)?[NSAttributedStringKey.link.rawValue],
        let urlString = (url as? String) ?? (url as? URL)?.absoluteString,
        urlString == "myurl"
    else { return }

    let url = URL(string: urlString)!
    // Do whatever you want with this URL, such as
    UIApplication.shared.openURL(url)
}

答案 4 :(得分:2)

有时它不能在iOS模拟器上运行,或者仅在您点击&持。

您应该在真实设备上进行测试。

不要忘记设置它selectable

答案 5 :(得分:1)

如果没有任何紧迫的理由使用UITextView,例如正在显示其他文字,您可以使用UILabelUITapGestureRecognizer相结合来获得效果您正在寻找。

否则,您可以选择实际的UIWebView

答案 6 :(得分:1)

您是否尝试过设置textview.delaysContentTouches = NO;?也许这可能有所帮助。

答案 7 :(得分:0)

如果你不需要编辑,你可以使用这个:

textView.isEditable = true
func textViewShouldBeginEditing(_ textView: UITextView) -> Bool
{
    return false
}